1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-02-15 13:33:36 +02:00

Moved selection logic to player state

This commit is contained in:
Ivan Savenko 2023-04-18 23:08:27 +03:00
parent e8718a46cc
commit bb08a0afc8
8 changed files with 97 additions and 82 deletions

View File

@ -405,6 +405,7 @@ void CPlayerInterface::heroKilled(const CGHeroInstance* hero)
{
EVENT_HANDLER_CALLED_BY_CLIENT;
LOG_TRACE_PARAMS(logGlobal, "Hero %s killed handler for player %s", hero->getNameTranslated() % playerID);
localState->removeWanderingHero(hero);
adventureInt->onHeroChanged(hero);
localState->erasePath(hero);
@ -2084,12 +2085,3 @@ void CPlayerInterface::showWorldViewEx(const std::vector<ObjectPosInfo>& objectP
EVENT_HANDLER_CALLED_BY_CLIENT;
adventureInt->openWorldView(objectPositions, showTerrain );
}
void CPlayerInterface::setSelection(const CArmedInstance *sel, bool centerView)
{
if (sel == localState->getCurrentArmy())
return;
localState->setSelection(sel);
adventureInt->onSelectionChanged(sel, centerView);
}

View File

@ -207,9 +207,6 @@ public: // public interface for use by client via LOCPLINT access
void showShipyardDialogOrProblemPopup(const IShipyard *obj); //obj may be town or shipyard;
void proposeLoadingGame();
/// Changes currently selected object
void setSelection(const CArmedInstance *sel, bool centerView = true);
///returns true if all events are processed internally
bool capturedAllEvents();

View File

@ -107,6 +107,41 @@ const CGHeroInstance * PlayerLocalState::getCurrentHero() const
return nullptr;
}
const CGHeroInstance * PlayerLocalState::getNextWanderingHero(const CGHeroInstance * currentHero)
{
bool currentHeroFound = false;
const CGHeroInstance * firstSuitable = nullptr;
const CGHeroInstance * nextSuitable = nullptr;
for(const auto * hero : getWanderingHeroes())
{
if (hero == currentHero)
{
currentHeroFound = true;
continue;
}
if (isHeroSleeping(hero))
continue;
if (hero->movement == 0)
continue;
if (!firstSuitable)
firstSuitable = hero;
if (!nextSuitable && currentHeroFound)
nextSuitable = hero;
}
// if we found suitable hero after currently selected hero -> return this hero
if (nextSuitable)
return nextSuitable;
// othervice -> loop over and return first suitable hero in the list (or null if none)
return firstSuitable;
}
const CGTownInstance * PlayerLocalState::getCurrentTown() const
{
if(currentSelection && currentSelection->ID == Obj::TOWN)
@ -125,7 +160,13 @@ const CArmedInstance * PlayerLocalState::getCurrentArmy() const
void PlayerLocalState::setSelection(const CArmedInstance * selection)
{
if (currentSelection == selection)
return;
currentSelection = selection;
if (selection)
adventureInt->onSelectionChanged(selection);
}
bool PlayerLocalState::isHeroSleeping(const CGHeroInstance * hero) const
@ -174,8 +215,21 @@ void PlayerLocalState::removeWanderingHero(const CGHeroInstance * hero)
{
assert(hero);
assert(vstd::contains(wanderingHeroes, hero));
if (hero == currentSelection)
{
auto const * nextHero = getNextWanderingHero(hero);
setSelection(nextHero);
}
vstd::erase(wanderingHeroes, hero);
vstd::erase(sleepingHeroes, hero);
if (currentSelection == nullptr && !wanderingHeroes.empty())
setSelection(wanderingHeroes.front());
if (currentSelection == nullptr && !ownedTowns.empty())
setSelection(ownedTowns.front());
}
const std::vector<const CGTownInstance *> & PlayerLocalState::getOwnedTowns()
@ -202,4 +256,13 @@ void PlayerLocalState::removeOwnedTown(const CGTownInstance * town)
assert(town);
assert(vstd::contains(ownedTowns, town));
vstd::erase(ownedTowns, town);
if (town == currentSelection)
setSelection(nullptr);
if (currentSelection == nullptr && !wanderingHeroes.empty())
setSelection(wanderingHeroes.front());
if (currentSelection == nullptr && !ownedTowns.empty())
setSelection(ownedTowns.front());
}

View File

@ -69,6 +69,7 @@ public:
const std::vector<const CGHeroInstance *> & getWanderingHeroes();
const CGHeroInstance * getWanderingHero(size_t index);
const CGHeroInstance * getNextWanderingHero(const CGHeroInstance * hero);
void addWanderingHero(const CGHeroInstance * hero);
void removeWanderingHero(const CGHeroInstance * hero);
@ -88,7 +89,7 @@ public:
const CArmedInstance * getCurrentArmy() const;
/// Changes currently selected object
void setSelection(const CArmedInstance * selection);
void setSelection(const CArmedInstance *sel);
template<typename Handler>
void serialize(Handler & h, int version)

View File

@ -287,9 +287,14 @@ void CAdventureMapInterface::fsleepWake()
if (!h)
return;
bool newSleep = !LOCPLINT->localState->isHeroSleeping(h);
setHeroSleeping(h, newSleep);
updateButtons();
if (newSleep)
LOCPLINT->localState->setHeroAsleep(h);
else
LOCPLINT->localState->setHeroAwaken(h);
onHeroChanged(h);
if (newSleep)
fnextHero();
@ -328,10 +333,14 @@ void CAdventureMapInterface::fsystemOptions()
void CAdventureMapInterface::fnextHero()
{
const auto * nextHero = getNextHero(LOCPLINT->localState->getCurrentHero());
const auto * currHero = LOCPLINT->localState->getCurrentHero();
const auto * nextHero = LOCPLINT->localState->getNextWanderingHero(currHero);
if (nextHero)
LOCPLINT->setSelection(nextHero, true);
{
LOCPLINT->localState->setSelection(nextHero);
centerOnObject(nextHero);
}
}
void CAdventureMapInterface::fendTurn()
@ -376,7 +385,7 @@ void CAdventureMapInterface::updateButtons()
spellbook->block(!hero);
moveHero->block(!hero || !LOCPLINT->localState->hasPath(hero) || hero->movement == 0);
const auto * nextSuitableHero = getNextHero(hero);
const auto * nextSuitableHero = LOCPLINT->localState->getNextWanderingHero(hero);
nextHero->block(nextSuitableHero == nullptr);
if(hero)
@ -388,41 +397,6 @@ void CAdventureMapInterface::updateButtons()
}
}
const CGHeroInstance * CAdventureMapInterface::getNextHero(const CGHeroInstance * currentHero)
{
bool currentHeroFound = false;
const CGHeroInstance * firstSuitable = nullptr;
const CGHeroInstance * nextSuitable = nullptr;
for(const auto * hero : LOCPLINT->localState->getWanderingHeroes())
{
if (hero == currentHero)
{
currentHeroFound = true;
continue;
}
if (LOCPLINT->localState->isHeroSleeping(hero))
continue;
if (hero->movement == 0)
continue;
if (!firstSuitable)
firstSuitable = hero;
if (!nextSuitable && currentHeroFound)
nextSuitable = hero;
}
// if we found suitable hero after currently selected hero -> return this hero
if (nextSuitable)
return nextSuitable;
// othervice -> loop over and return first suitable hero in the list (or null if none)
return firstSuitable;
}
void CAdventureMapInterface::onHeroChanged(const CGHeroInstance *h)
{
heroList->update(h);
@ -522,16 +496,6 @@ void CAdventureMapInterface::showAll(SDL_Surface * to)
LOCPLINT->cingconsole->show(to);
}
void CAdventureMapInterface::setHeroSleeping(const CGHeroInstance *hero, bool sleep)
{
if (sleep)
LOCPLINT->localState->setHeroAsleep(hero);
else
LOCPLINT->localState->setHeroAwaken(hero);
onHeroChanged(hero);
}
void CAdventureMapInterface::show(SDL_Surface * to)
{
// if(state != EGameState::MAKING_TURN)
@ -818,13 +782,15 @@ std::optional<Point> CAdventureMapInterface::keyToMoveDirection(const SDL_Keycod
return std::nullopt;
}
void CAdventureMapInterface::onSelectionChanged(const CArmedInstance *sel, bool centerView)
void CAdventureMapInterface::onSelectionChanged(const CArmedInstance *sel)
{
assert(sel);
infoBar->popAll();
mapAudio->onSelectionChanged(sel);
if(centerView)
bool centerView = !settings["session"]["autoSkip"].Bool();
if (centerView)
centerOnObject(sel);
if(sel->ID==Obj::TOWN)
@ -944,20 +910,18 @@ void CAdventureMapInterface::onPlayerTurnStarted(PlayerColor playerID)
}
}
bool centerView = !settings["session"]["autoSkip"].Bool();
//select first hero if available.
if (heroToSelect != nullptr)
{
LOCPLINT->setSelection(heroToSelect, centerView);
LOCPLINT->localState->setSelection(heroToSelect);
}
else if (LOCPLINT->localState->getOwnedTowns().size())
{
LOCPLINT->setSelection(LOCPLINT->localState->getOwnedTown(0), centerView);
LOCPLINT->localState->setSelection(LOCPLINT->localState->getOwnedTown(0));
}
else
{
LOCPLINT->setSelection(LOCPLINT->localState->getWanderingHero(0), centerView);
LOCPLINT->localState->setSelection(LOCPLINT->localState->getWanderingHero(0));
}
//show new day animation and sound on infobar
@ -1044,7 +1008,7 @@ void CAdventureMapInterface::onTileLeftClicked(const int3 &mapPos)
if(LOCPLINT->localState->getCurrentArmy() == topBlocking) //selected town clicked
LOCPLINT->openTownWindow(static_cast<const CGTownInstance*>(topBlocking));
else if(canSelect)
LOCPLINT->setSelection(static_cast<const CArmedInstance*>(topBlocking), false);
LOCPLINT->localState->setSelection(static_cast<const CArmedInstance*>(topBlocking));
}
else if(const CGHeroInstance * currentHero = LOCPLINT->localState->getCurrentHero()) //hero is selected
{
@ -1058,7 +1022,7 @@ void CAdventureMapInterface::onTileLeftClicked(const int3 &mapPos)
}
else if(canSelect && pn->turns == 255 ) //selectable object at inaccessible tile
{
LOCPLINT->setSelection(static_cast<const CArmedInstance*>(topBlocking), false);
LOCPLINT->localState->setSelection(static_cast<const CArmedInstance*>(topBlocking));
return;
}
else //still here? we need to move hero if we clicked end of already selected path or calculate a new path otherwise

View File

@ -132,8 +132,6 @@ private:
std::optional<Point> keyToMoveDirection(const SDL_Keycode & key);
void setHeroSleeping(const CGHeroInstance *hero, bool sleep);
const CGHeroInstance * getNextHero(const CGHeroInstance * currentHero); //for Next Hero button - cycles awake heroes with movement only
void endingTurn();
/// exits currently opened world view mode and returns to normal map
@ -176,8 +174,8 @@ public:
/// Called by PlayerInterface when town state changed and town list must be updated
void onTownChanged(const CGTownInstance * town);
/// Changes currently selected object
void onSelectionChanged(const CArmedInstance *sel, bool centerView = true);
/// Called when currently selected object changes
void onSelectionChanged(const CArmedInstance *sel);
/// Called when map audio should be paused, e.g. on combat or town screen access
void onAudioPaused();

View File

@ -204,8 +204,8 @@ std::shared_ptr<CIntObject> CHeroList::CHeroItem::genSelection()
void CHeroList::CHeroItem::select(bool on)
{
if(on && LOCPLINT->localState->getCurrentHero() != hero)
LOCPLINT->setSelection(hero);
if(on)
LOCPLINT->localState->setSelection(hero);
}
void CHeroList::CHeroItem::open()
@ -293,8 +293,8 @@ void CTownList::CTownItem::update()
void CTownList::CTownItem::select(bool on)
{
if (on && LOCPLINT->localState->getCurrentTown() != town)
LOCPLINT->setSelection(town, true);
if(on)
LOCPLINT->localState->setSelection(town);
}
void CTownList::CTownItem::open()

View File

@ -1230,9 +1230,9 @@ void CCastleInterface::close()
if(town->tempOwner == LOCPLINT->playerID) //we may have opened window for an allied town
{
if(town->visitingHero && town->visitingHero->tempOwner == LOCPLINT->playerID)
LOCPLINT->setSelection(town->visitingHero);
LOCPLINT->localState->setSelection(town->visitingHero);
else
LOCPLINT->setSelection(town);
LOCPLINT->localState->setSelection(town);
}
CWindowObject::close();
}