1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-03-29 21:56:54 +02:00

Moved player-specific heroes & towns information to new class

This commit is contained in:
Ivan Savenko 2023-04-17 02:02:31 +03:00
parent 4a169972f0
commit f6d480cbb2
11 changed files with 285 additions and 244 deletions

View File

@ -110,6 +110,7 @@ set(client_SRCS
CMT.cpp
CMusicHandler.cpp
CPlayerInterface.cpp
PlayerLocalState.cpp
CServerHandler.cpp
CVideoHandler.cpp
Client.cpp
@ -238,6 +239,7 @@ set(client_HEADERS
CMT.h
CMusicHandler.h
CPlayerInterface.h
PlayerLocalState.h
CServerHandler.h
CVideoHandler.h
Client.h

View File

@ -8,6 +8,7 @@
*
*/
#include "StdInc.h"
#include "CPlayerInterface.h"
#include <vcmi/Artifact.h>
@ -25,12 +26,12 @@
#include "gui/CursorHandler.h"
#include "windows/CKingdomInterface.h"
#include "CGameInfo.h"
#include "PlayerLocalState.h"
#include "CMT.h"
#include "windows/CHeroWindow.h"
#include "windows/CCreatureWindow.h"
#include "windows/CQuestLog.h"
#include "windows/CPuzzleWindow.h"
#include "CPlayerInterface.h"
#include "widgets/CComponent.h"
#include "widgets/Buttons.h"
#include "windows/CTradeWindow.h"
@ -114,96 +115,8 @@ struct HeroObjectRetriever
}
};
HeroPathStorage::HeroPathStorage(CPlayerInterface & owner):
owner(owner)
{
}
void HeroPathStorage::setPath(const CGHeroInstance *h, const CGPath & path)
{
paths[h] = path;
}
const CGPath & HeroPathStorage::getPath(const CGHeroInstance *h) const
{
assert(hasPath(h));
return paths.at(h);
}
bool HeroPathStorage::hasPath(const CGHeroInstance *h) const
{
return paths.count(h) > 0;
}
bool HeroPathStorage::setPath(const CGHeroInstance *h, const int3 & destination)
{
CGPath path;
if (!owner.cb->getPathsInfo(h)->getPath(path, destination))
return false;
setPath(h, path);
return true;
}
void HeroPathStorage::removeLastNode(const CGHeroInstance *h)
{
assert(hasPath(h));
if (!hasPath(h))
return;
auto & path = paths[h];
path.nodes.pop_back();
if (path.nodes.size() < 2) //if it was the last one, remove entire path and path with only one tile is not a real path
erasePath(h);
}
void HeroPathStorage::erasePath(const CGHeroInstance *h)
{
paths.erase(h);
adventureInt->onHeroChanged(h);
}
void HeroPathStorage::verifyPath(const CGHeroInstance *h)
{
if (!hasPath(h))
return;
setPath(h, getPath(h).endPos());
}
template<typename Handler>
void HeroPathStorage::serialize(Handler & h, int version)
{
std::map<const CGHeroInstance *, int3> pathsMap; //hero -> dest
if (h.saving)
{
for (auto &p : paths)
{
if (p.second.nodes.size())
pathsMap[p.first] = p.second.endPos();
else
logGlobal->debug("%s has assigned an empty path! Ignoring it...", p.first->getNameTranslated());
}
h & pathsMap;
}
else
{
h & pathsMap;
if (owner.cb)
{
for (auto &p : pathsMap)
{
CGPath path;
owner.cb->getPathsInfo(p.first)->getPath(path, p.second);
paths[p.first] = path;
logGlobal->trace("Restored path for hero %s leading to %s with %d nodes", p.first->nodeName(), p.second.toString(), path.nodes.size());
}
}
}
}
CPlayerInterface::CPlayerInterface(PlayerColor Player):
paths(*this)
localState(std::make_unique<PlayerLocalState>(*this))
{
logGlobal->trace("\tHuman player interface for player %s being constructed", Player.getStr());
destinationTeleport = ObjectInstanceID();
@ -401,27 +314,27 @@ void CPlayerInterface::heroMoved(const TryMoveHero & details, bool verbose)
};
adventureInt->onMapTilesChanged(changedTiles);
bool directlyAttackingCreature = details.attackedFrom && paths.hasPath(hero) && paths.getPath(hero).endPos() == *details.attackedFrom;
bool directlyAttackingCreature = details.attackedFrom && localState->hasPath(hero) && localState->getPath(hero).endPos() == *details.attackedFrom;
if(makingTurn && hero->tempOwner == playerID) //we are moving our hero - we may need to update assigned path
{
if(details.result == TryMoveHero::TELEPORTATION)
{
if(paths.hasPath(hero))
if(localState->hasPath(hero))
{
assert(paths.getPath(hero).nodes.size() >= 2);
auto nodesIt = paths.getPath(hero).nodes.end() - 1;
assert(localState->getPath(hero).nodes.size() >= 2);
auto nodesIt = localState->getPath(hero).nodes.end() - 1;
if((nodesIt)->coord == hero->convertToVisitablePos(details.start)
&& (nodesIt - 1)->coord == hero->convertToVisitablePos(details.end))
{
//path was between entrance and exit of teleport -> OK, erase node as usual
paths.removeLastNode(hero);
localState->removeLastNode(hero);
}
else
{
//teleport was not along current path, it'll now be invalid (hero is somewhere else)
paths.erasePath(hero);
localState->erasePath(hero);
}
}
@ -430,12 +343,12 @@ void CPlayerInterface::heroMoved(const TryMoveHero & details, bool verbose)
if(hero->pos != details.end //hero didn't change tile but visit succeeded
|| directlyAttackingCreature) // or creature was attacked from endangering tile.
{
paths.erasePath(hero);
localState->erasePath(hero);
}
else if(paths.hasPath(hero) && hero->pos == details.end) //&& hero is moving
else if(localState->hasPath(hero) && hero->pos == details.end) //&& hero is moving
{
if(details.start != details.end) //so we don't touch path when revisiting with spacebar
paths.removeLastNode(hero);
localState->removeLastNode(hero);
}
}
@ -492,9 +405,9 @@ 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);
wanderingHeroes -= hero;
localState->wanderingHeroes -= hero;
adventureInt->onHeroChanged(hero);
paths.erasePath(hero);
localState->erasePath(hero);
}
void CPlayerInterface::heroVisit(const CGHeroInstance * visitor, const CGObjectInstance * visitedObj, bool start)
@ -510,7 +423,7 @@ void CPlayerInterface::heroVisit(const CGHeroInstance * visitor, const CGObjectI
void CPlayerInterface::heroCreated(const CGHeroInstance * hero)
{
EVENT_HANDLER_CALLED_BY_CLIENT;
wanderingHeroes.push_back(hero);
localState->wanderingHeroes.push_back(hero);
adventureInt->onHeroChanged(hero);
}
void CPlayerInterface::openTownWindow(const CGTownInstance * town)
@ -596,14 +509,14 @@ void CPlayerInterface::heroInGarrisonChange(const CGTownInstance *town)
if (town->garrisonHero) //wandering hero moved to the garrison
{
if (town->garrisonHero->tempOwner == playerID && vstd::contains(wanderingHeroes,town->garrisonHero)) // our hero
wanderingHeroes -= town->garrisonHero;
if (town->garrisonHero->tempOwner == playerID && vstd::contains(localState->wanderingHeroes,town->garrisonHero)) // our hero
localState->wanderingHeroes -= town->garrisonHero;
}
if (town->visitingHero) //hero leaves garrison
{
if (town->visitingHero->tempOwner == playerID && !vstd::contains(wanderingHeroes,town->visitingHero)) // our hero
wanderingHeroes.push_back(town->visitingHero);
if (town->visitingHero->tempOwner == playerID && !vstd::contains(localState->wanderingHeroes,town->visitingHero)) // our hero
localState->wanderingHeroes.push_back(town->visitingHero);
}
adventureInt->onHeroChanged(nullptr);
adventureInt->onTownChanged(town);
@ -1311,29 +1224,20 @@ void CPlayerInterface::heroBonusChanged( const CGHeroInstance *hero, const Bonus
if ((bonus.type == Bonus::FLYING_MOVEMENT || bonus.type == Bonus::WATER_WALKING) && !gain)
{
//recalculate paths because hero has lost bonus influencing pathfinding
paths.erasePath(hero);
localState->erasePath(hero);
}
}
template <typename Handler> void CPlayerInterface::serializeTempl( Handler &h, const int version )
{
h & wanderingHeroes;
h & towns;
h & sleepingHeroes;
h & paths;
h & spellbookSettings;
}
void CPlayerInterface::saveGame( BinarySerializer & h, const int version )
{
EVENT_HANDLER_CALLED_BY_CLIENT;
serializeTempl(h,version);
h & localState;
}
void CPlayerInterface::loadGame( BinaryDeserializer & h, const int version )
{
EVENT_HANDLER_CALLED_BY_CLIENT;
serializeTempl(h,version);
h & localState;
firstCall = -1;
}
@ -1362,7 +1266,7 @@ void CPlayerInterface::showGarrisonDialog( const CArmedInstance *up, const CGHer
EVENT_HANDLER_CALLED_BY_CLIENT;
auto onEnd = [=](){ cb->selectionMade(0, queryID); };
if (stillMoveHero.get() == DURING_MOVE && paths.hasPath(down) && paths.getPath(down).nodes.size() > 1) //to ignore calls on passing through garrisons
if (stillMoveHero.get() == DURING_MOVE && localState->hasPath(down) && localState->getPath(down).nodes.size() > 1) //to ignore calls on passing through garrisons
{
onEnd();
return;
@ -1441,9 +1345,9 @@ void CPlayerInterface::objectPropertyChanged(const SetObjectProperty * sop)
auto town = static_cast<const CGTownInstance *>(obj);
if(obj->tempOwner == playerID)
towns.push_back(town);
localState->ownedTowns.push_back(town);
else
towns -= obj;
localState->ownedTowns -= obj;
adventureInt->onTownChanged(town);
}
@ -1452,24 +1356,24 @@ void CPlayerInterface::objectPropertyChanged(const SetObjectProperty * sop)
std::unordered_set<int3> upos(pos.begin(), pos.end());
adventureInt->onMapTilesChanged(upos);
assert(cb->getTownsInfo().size() == towns.size());
assert(cb->getTownsInfo().size() == localState->ownedTowns.size());
}
}
void CPlayerInterface::initializeHeroTownList()
{
if(!wanderingHeroes.size())
if(!localState->wanderingHeroes.size())
{
std::vector<const CGHeroInstance*> heroes = cb->getHeroesInfo();
for(auto & hero : heroes)
{
if(!hero->inTownGarrison)
wanderingHeroes.push_back(hero);
localState->wanderingHeroes.push_back(hero);
}
}
if(!towns.size())
towns = cb->getTownsInfo();
if(!localState->ownedTowns.size())
localState->ownedTowns = cb->getTownsInfo();
if(adventureInt)
adventureInt->onHeroChanged(nullptr);
@ -1736,7 +1640,7 @@ void CPlayerInterface::advmapSpellCast(const CGHeroInstance * caster, int spellI
GH.popInts(1);
if(spellID == SpellID::FLY || spellID == SpellID::WATER_WALK)
paths.erasePath(caster);
localState->erasePath(caster);
const spells::Spell * spell = CGI->spells()->getByIndex(spellID);
auto castSoundPath = spell->getCastSound();
@ -1972,12 +1876,6 @@ void CPlayerInterface::proposeLoadingGame()
showYesNoDialog(CGI->generaltexth->allTexts[68], [](){ GH.pushUserEvent(EUserEvent::RETURN_TO_MENU_LOAD); }, nullptr);
}
CPlayerInterface::SpellbookLastSetting::SpellbookLastSetting()
{
spellbookLastPageBattle = spellbokLastPageAdvmap = 0;
spellbookLastTabBattle = spellbookLastTabAdvmap = 4;
}
bool CPlayerInterface::capturedAllEvents()
{
if(duringMovement)

View File

@ -9,16 +9,10 @@
*/
#pragma once
#include "../lib/FunctionList.h"
#include "../lib/CGameInterface.h"
#include "../lib/NetPacksBase.h"
#include "gui/CIntObject.h"
#ifdef __GNUC__
#define sprintf_s snprintf
#endif
VCMI_LIB_NAMESPACE_BEGIN
class Artifact;
@ -51,43 +45,16 @@ class ClickableR;
class Hoverable;
class KeyInterested;
class MotionInterested;
class PlayerLocalState;
class TimeInterested;
class IShowable;
struct SDL_Surface;
union SDL_Event;
namespace boost
{
class mutex;
class recursive_mutex;
}
class CPlayerInterface;
class HeroPathStorage
{
CPlayerInterface & owner;
std::map<const CGHeroInstance *, CGPath> paths; //maps hero => selected path in adventure map
public:
explicit HeroPathStorage(CPlayerInterface &owner);
void setPath(const CGHeroInstance *h, const CGPath & path);
bool setPath(const CGHeroInstance *h, const int3 & destination);
const CGPath & getPath(const CGHeroInstance *h) const;
bool hasPath(const CGHeroInstance *h) const;
void removeLastNode(const CGHeroInstance *h);
void erasePath(const CGHeroInstance *h);
void verifyPath(const CGHeroInstance *h);
template <typename Handler>
void serialize( Handler &h, int version );
};
/// Central class for managing user interface logic
class CPlayerInterface : public CGameInterface, public IUpdateable
{
@ -107,7 +74,7 @@ class CPlayerInterface : public CGameInterface, public IUpdateable
public: // TODO: make private
std::shared_ptr<Environment> env;
HeroPathStorage paths;
std::unique_ptr<PlayerLocalState> localState;
//minor interfaces
CondSh<bool> *showingDialog; //indicates if dialog box is displayed
@ -121,29 +88,10 @@ public: // TODO: make private
std::shared_ptr<CCallback> cb; //to communicate with engine
std::vector<const CGHeroInstance *> wanderingHeroes; //our heroes on the adventure map (not the garrisoned ones)
std::vector<const CGTownInstance *> towns; //our towns on the adventure map
std::vector<const CGHeroInstance *> sleepingHeroes; //if hero is in here, he's sleeping
//During battle is quick combat mode is used
std::shared_ptr<CBattleGameInterface> autofightingAI; //AI that makes decisions
bool isAutoFightOn; //Flag, switch it to stop quick combat. Don't touch if there is no battle interface.
struct SpellbookLastSetting
{
int spellbookLastPageBattle, spellbokLastPageAdvmap; //on which page we left spellbook
int spellbookLastTabBattle, spellbookLastTabAdvmap; //on which page we left spellbook
SpellbookLastSetting();
template <typename Handler> void serialize( Handler &h, const int version )
{
h & spellbookLastPageBattle;
h & spellbokLastPageAdvmap;
h & spellbookLastTabBattle;
h & spellbookLastTabAdvmap;
}
} spellbookSettings;
public:
void update() override;
void initializeHeroTownList();
@ -267,8 +215,6 @@ public:
~CPlayerInterface();
private:
template <typename Handler> void serializeTempl(Handler &h, const int version);
struct IgnoreEvents
{
CPlayerInterface & owner;

105
client/PlayerLocalState.cpp Normal file
View File

@ -0,0 +1,105 @@
/*
* PlayerLocalState.cpp, part of VCMI engine
*
* Authors: listed in file AUTHORS in main folder
*
* License: GNU General Public License v2.0 or later
* Full text of license available in license.txt file, in main folder
*
*/
#include "StdInc.h"
#include "PlayerLocalState.h"
#include "../CCallback.h"
#include "../lib/CPathfinder.h"
#include "../lib/mapObjects/CGHeroInstance.h"
#include "CPlayerInterface.h"
#include "adventureMap/CAdventureMapInterface.h"
PlayerLocalState::PlayerLocalState()
: owner(*LOCPLINT)
{
// should never be called, method required for serializer methods template instantiations
throw std::runtime_error("Can not create PlayerLocalState without interface!");
}
PlayerLocalState::PlayerLocalState(CPlayerInterface & owner)
: owner(owner)
{
}
void PlayerLocalState::saveHeroPaths(std::map<const CGHeroInstance *, int3> & pathsMap)
{
for(auto & p : paths)
{
if(p.second.nodes.size())
pathsMap[p.first] = p.second.endPos();
else
logGlobal->debug("%s has assigned an empty path! Ignoring it...", p.first->getNameTranslated());
}
}
void PlayerLocalState::loadHeroPaths(std::map<const CGHeroInstance *, int3> & pathsMap)
{
if(owner.cb)
{
for(auto & p : pathsMap)
{
CGPath path;
owner.cb->getPathsInfo(p.first)->getPath(path, p.second);
paths[p.first] = path;
logGlobal->trace("Restored path for hero %s leading to %s with %d nodes", p.first->nodeName(), p.second.toString(), path.nodes.size());
}
}
}
void PlayerLocalState::setPath(const CGHeroInstance * h, const CGPath & path)
{
paths[h] = path;
}
const CGPath & PlayerLocalState::getPath(const CGHeroInstance * h) const
{
assert(hasPath(h));
return paths.at(h);
}
bool PlayerLocalState::hasPath(const CGHeroInstance * h) const
{
return paths.count(h) > 0;
}
bool PlayerLocalState::setPath(const CGHeroInstance * h, const int3 & destination)
{
CGPath path;
if(!owner.cb->getPathsInfo(h)->getPath(path, destination))
return false;
setPath(h, path);
return true;
}
void PlayerLocalState::removeLastNode(const CGHeroInstance * h)
{
assert(hasPath(h));
if(!hasPath(h))
return;
auto & path = paths[h];
path.nodes.pop_back();
if(path.nodes.size() < 2) //if it was the last one, remove entire path and path with only one tile is not a real path
erasePath(h);
}
void PlayerLocalState::erasePath(const CGHeroInstance * h)
{
paths.erase(h);
adventureInt->onHeroChanged(h);
}
void PlayerLocalState::verifyPath(const CGHeroInstance * h)
{
if(!hasPath(h))
return;
setPath(h, getPath(h).endPos());
}

84
client/PlayerLocalState.h Normal file
View File

@ -0,0 +1,84 @@
/*
* PlayerLocalState.h, part of VCMI engine
*
* Authors: listed in file AUTHORS in main folder
*
* License: GNU General Public License v2.0 or later
* Full text of license available in license.txt file, in main folder
*
*/
#pragma once
VCMI_LIB_NAMESPACE_BEGIN
class CGHeroInstance;
class CGTownInstance;
struct CGPath;
class int3;
VCMI_LIB_NAMESPACE_END
class CPlayerInterface;
/// Class that contains potentially serializeable state of a local player
class PlayerLocalState
{
CPlayerInterface & owner;
std::map<const CGHeroInstance *, CGPath> paths; //maps hero => selected path in adventure map
void saveHeroPaths(std::map<const CGHeroInstance *, int3> & paths);
void loadHeroPaths(std::map<const CGHeroInstance *, int3> & paths);
public:
struct SpellbookLastSetting
{
//on which page we left spellbook
int spellbookLastPageBattle = 0;
int spellbokLastPageAdvmap = 0;
int spellbookLastTabBattle = 4;
int spellbookLastTabAdvmap = 4;
template <typename Handler> void serialize( Handler &h, const int version )
{
h & spellbookLastPageBattle;
h & spellbokLastPageAdvmap;
h & spellbookLastTabBattle;
h & spellbookLastTabAdvmap;
}
} spellbookSettings;
std::vector<const CGHeroInstance *> wanderingHeroes; //our heroes on the adventure map (not the garrisoned ones)
std::vector<const CGTownInstance *> ownedTowns; //our towns on the adventure map
std::vector<const CGHeroInstance *> sleepingHeroes; //if hero is in here, he's sleeping
PlayerLocalState();
explicit PlayerLocalState(CPlayerInterface & owner);
void setPath(const CGHeroInstance *h, const CGPath & path);
bool setPath(const CGHeroInstance *h, const int3 & destination);
const CGPath & getPath(const CGHeroInstance *h) const;
bool hasPath(const CGHeroInstance *h) const;
void removeLastNode(const CGHeroInstance *h);
void erasePath(const CGHeroInstance *h);
void verifyPath(const CGHeroInstance *h);
template <typename Handler>
void serialize( Handler &h, int version )
{
//WARNING: this code is broken and not used. See CClient::loadGame
std::map<const CGHeroInstance *, int3> pathsMap; //hero -> dest
if(h.saving)
saveHeroPaths(pathsMap);
h & pathsMap;
if(!h.saving)
loadHeroPaths(pathsMap);
h & ownedTowns;
h & wanderingHeroes;
h & sleepingHeroes;
}
};

View File

@ -38,6 +38,7 @@
#include "../widgets/Buttons.h"
#include "../windows/settings/SettingsMainWindow.h"
#include "../CMT.h"
#include "../PlayerLocalState.h"
#include "../../CCallback.h"
#include "../../lib/CConfigHandler.h"
@ -309,10 +310,10 @@ void CAdventureMapInterface::fsleepWake()
void CAdventureMapInterface::fmoveHero()
{
const CGHeroInstance *h = getCurrentHero();
if (!h || !LOCPLINT->paths.hasPath(h) || CGI->mh->hasOngoingAnimations())
if (!h || !LOCPLINT->localState->hasPath(h) || CGI->mh->hasOngoingAnimations())
return;
LOCPLINT->moveHero(h, LOCPLINT->paths.getPath(h));
LOCPLINT->moveHero(h, LOCPLINT->localState->getPath(h));
}
void CAdventureMapInterface::fshowSpellbok()
@ -338,10 +339,10 @@ void CAdventureMapInterface::fsystemOptions()
void CAdventureMapInterface::fnextHero()
{
auto hero = dynamic_cast<const CGHeroInstance*>(currentSelection);
int next = getNextHeroIndex(vstd::find_pos(LOCPLINT->wanderingHeroes, hero));
int next = getNextHeroIndex(vstd::find_pos(LOCPLINT->localState->wanderingHeroes, hero));
if (next < 0)
return;
setSelection(LOCPLINT->wanderingHeroes[next], true);
setSelection(LOCPLINT->localState->wanderingHeroes[next], true);
}
void CAdventureMapInterface::fendTurn()
@ -351,22 +352,22 @@ void CAdventureMapInterface::fendTurn()
if(settings["adventure"]["heroReminder"].Bool())
{
for(auto hero : LOCPLINT->wanderingHeroes)
for(auto hero : LOCPLINT->localState->wanderingHeroes)
{
if(!isHeroSleeping(hero) && hero->movement > 0)
{
// Only show hero reminder if conditions met:
// - There still movement points
// - Hero don't have a path or there not points for first step on path
LOCPLINT->paths.verifyPath(hero);
LOCPLINT->localState->verifyPath(hero);
if(!LOCPLINT->paths.hasPath(hero))
if(!LOCPLINT->localState->hasPath(hero))
{
LOCPLINT->showYesNoDialog( CGI->generaltexth->allTexts[55], std::bind(&CAdventureMapInterface::endingTurn, this), nullptr );
return;
}
auto path = LOCPLINT->paths.getPath(hero);
auto path = LOCPLINT->localState->getPath(hero);
if (path.nodes.size() < 2 || path.nodes[path.nodes.size() - 2].turns)
{
LOCPLINT->showYesNoDialog( CGI->generaltexth->allTexts[55], std::bind(&CAdventureMapInterface::endingTurn, this), nullptr );
@ -396,7 +397,7 @@ void CAdventureMapInterface::updateSpellbook(const CGHeroInstance *h)
int CAdventureMapInterface::getNextHeroIndex(int startIndex)
{
if (LOCPLINT->wanderingHeroes.size() == 0)
if (LOCPLINT->localState->wanderingHeroes.size() == 0)
return -1;
if (startIndex < 0)
startIndex = 0;
@ -404,12 +405,12 @@ int CAdventureMapInterface::getNextHeroIndex(int startIndex)
do
{
i++;
if (i >= LOCPLINT->wanderingHeroes.size())
if (i >= LOCPLINT->localState->wanderingHeroes.size())
i = 0;
}
while (((LOCPLINT->wanderingHeroes[i]->movement == 0) || isHeroSleeping(LOCPLINT->wanderingHeroes[i])) && (i != startIndex));
while (((LOCPLINT->localState->wanderingHeroes[i]->movement == 0) || isHeroSleeping(LOCPLINT->localState->wanderingHeroes[i])) && (i != startIndex));
if ((LOCPLINT->wanderingHeroes[i]->movement != 0) && !isHeroSleeping(LOCPLINT->wanderingHeroes[i]))
if ((LOCPLINT->localState->wanderingHeroes[i]->movement != 0) && !isHeroSleeping(LOCPLINT->localState->wanderingHeroes[i]))
return i;
else
return -1;
@ -422,14 +423,14 @@ void CAdventureMapInterface::onHeroChanged(const CGHeroInstance *h)
if (h == getCurrentHero())
infoBar->showSelection();
int start = vstd::find_pos(LOCPLINT->wanderingHeroes, h);
int start = vstd::find_pos(LOCPLINT->localState->wanderingHeroes, h);
int next = getNextHeroIndex(start);
if (next < 0)
{
nextHero->block(true);
return;
}
const CGHeroInstance *nextH = LOCPLINT->wanderingHeroes[next];
const CGHeroInstance *nextH = LOCPLINT->localState->wanderingHeroes[next];
bool noActiveHeroes = (next == start) && ((nextH->movement == 0) || isHeroSleeping(nextH));
nextHero->block(noActiveHeroes);
@ -439,7 +440,7 @@ void CAdventureMapInterface::onHeroChanged(const CGHeroInstance *h)
return;
}
//default value is for everywhere but CPlayerInterface::moveHero, because paths are not updated from there immediately
bool hasPath = LOCPLINT->paths.hasPath(h);
bool hasPath = LOCPLINT->localState->hasPath(h);
moveHero->block(!(bool)hasPath || (h->movement == 0));
}
@ -538,7 +539,7 @@ bool CAdventureMapInterface::isHeroSleeping(const CGHeroInstance *hero)
if (!hero)
return false;
return vstd::contains(LOCPLINT->sleepingHeroes, hero);
return vstd::contains(LOCPLINT->localState->sleepingHeroes, hero);
}
void CAdventureMapInterface::onHeroWokeUp(const CGHeroInstance * hero)
@ -556,9 +557,9 @@ void CAdventureMapInterface::onHeroWokeUp(const CGHeroInstance * hero)
void CAdventureMapInterface::setHeroSleeping(const CGHeroInstance *hero, bool sleep)
{
if (sleep)
LOCPLINT->sleepingHeroes.push_back(hero); //FIXME: should we check for existence?
LOCPLINT->localState->sleepingHeroes.push_back(hero); //FIXME: should we check for existence?
else
LOCPLINT->sleepingHeroes -= hero;
LOCPLINT->localState->sleepingHeroes -= hero;
onHeroChanged(hero);
}
@ -654,7 +655,7 @@ void CAdventureMapInterface::handleMapScrollingUpdate()
void CAdventureMapInterface::selectionChanged()
{
const CGTownInstance *to = LOCPLINT->towns[townList->getSelectedIndex()];
const CGTownInstance *to = LOCPLINT->localState->ownedTowns[townList->getSelectedIndex()];
if (currentSelection != to)
setSelection(to);
}
@ -685,12 +686,12 @@ void CAdventureMapInterface::keyPressed(const SDL_Keycode & key)
{
//find first town with tavern
auto itr = range::find_if(LOCPLINT->towns, [](const CGTownInstance * town)
auto itr = range::find_if(LOCPLINT->localState->ownedTowns, [](const CGTownInstance * town)
{
return town->hasBuilt(BuildingID::TAVERN);
});
if(itr != LOCPLINT->towns.end())
if(itr != LOCPLINT->localState->ownedTowns.end())
LOCPLINT->showThievesGuildWindow(*itr);
else
LOCPLINT->showInfoDialog(CGI->generaltexth->translate("vcmi.adventureMap.noTownWithTavern"));
@ -819,10 +820,10 @@ void CAdventureMapInterface::keyPressed(const SDL_Keycode & key)
if (!CGI->mh->isInMap((dst)))
return;
if ( !LOCPLINT->paths.setPath(h, dst))
if ( !LOCPLINT->localState->setPath(h, dst))
return;
const CGPath & path = LOCPLINT->paths.getPath(h);
const CGPath & path = LOCPLINT->localState->getPath(h);
if (path.nodes.size() > 2)
onHeroChanged(h);
@ -885,7 +886,7 @@ void CAdventureMapInterface::setSelection(const CArmedInstance *sel, bool center
heroList->select(hero);
townList->select(nullptr);
LOCPLINT->paths.verifyPath(hero);
LOCPLINT->localState->verifyPath(hero);
updateSleepWake(hero);
onHeroChanged(hero);
@ -978,9 +979,9 @@ void CAdventureMapInterface::onPlayerTurnStarted(PlayerColor playerID)
const CGHeroInstance * heroToSelect = nullptr;
// find first non-sleeping hero
for (auto hero : LOCPLINT->wanderingHeroes)
for (auto hero : LOCPLINT->localState->wanderingHeroes)
{
if (boost::range::find(LOCPLINT->sleepingHeroes, hero) == LOCPLINT->sleepingHeroes.end())
if (boost::range::find(LOCPLINT->localState->sleepingHeroes, hero) == LOCPLINT->localState->sleepingHeroes.end())
{
heroToSelect = hero;
break;
@ -994,10 +995,10 @@ void CAdventureMapInterface::onPlayerTurnStarted(PlayerColor playerID)
{
setSelection(heroToSelect, centerView);
}
else if (LOCPLINT->towns.size())
setSelection(LOCPLINT->towns.front(), centerView);
else if (LOCPLINT->localState->ownedTowns.size())
setSelection(LOCPLINT->localState->ownedTowns.front(), centerView);
else
setSelection(LOCPLINT->wanderingHeroes.front());
setSelection(LOCPLINT->localState->wanderingHeroes.front());
//show new day animation and sound on infobar
infoBar->showDate();
@ -1102,16 +1103,16 @@ void CAdventureMapInterface::onTileLeftClicked(const int3 &mapPos)
}
else //still here? we need to move hero if we clicked end of already selected path or calculate a new path otherwise
{
if(LOCPLINT->paths.hasPath(currentHero) &&
LOCPLINT->paths.getPath(currentHero).endPos() == mapPos)//we'll be moving
if(LOCPLINT->localState->hasPath(currentHero) &&
LOCPLINT->localState->getPath(currentHero).endPos() == mapPos)//we'll be moving
{
if(!CGI->mh->hasOngoingAnimations())
LOCPLINT->moveHero(currentHero, LOCPLINT->paths.getPath(currentHero));
LOCPLINT->moveHero(currentHero, LOCPLINT->localState->getPath(currentHero));
return;
}
else //remove old path and find a new one if we clicked on accessible tile
{
LOCPLINT->paths.setPath(currentHero, mapPos);
LOCPLINT->localState->setPath(currentHero, mapPos);
onHeroChanged(currentHero);
}
}

View File

@ -22,6 +22,7 @@
#include "../CGameInfo.h"
#include "../CMusicHandler.h"
#include "../CPlayerInterface.h"
#include "../PlayerLocalState.h"
#include "../gui/CGuiHandler.h"
#include "../../CCallback.h"
@ -114,7 +115,7 @@ CInfoBar::VisibleGameStatusInfo::VisibleGameStatusInfo()
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
//get amount of halls of each level
std::vector<int> halls(4, 0);
for(auto town : LOCPLINT->towns)
for(auto town : LOCPLINT->localState->ownedTowns)
{
int hallLevel = town->hallLevel();
//negative value means no village hall, unlikely but possible

View File

@ -18,6 +18,7 @@
#include "../windows/InfoWindows.h"
#include "../CGameInfo.h"
#include "../CPlayerInterface.h"
#include "../PlayerLocalState.h"
#include "../gui/CGuiHandler.h"
#include "../../lib/CGeneralTextHandler.h"
@ -224,19 +225,19 @@ std::string CHeroList::CHeroItem::getHoverText()
std::shared_ptr<CIntObject> CHeroList::createHeroItem(size_t index)
{
if (LOCPLINT->wanderingHeroes.size() > index)
return std::make_shared<CHeroItem>(this, LOCPLINT->wanderingHeroes[index]);
if (LOCPLINT->localState->wanderingHeroes.size() > index)
return std::make_shared<CHeroItem>(this, LOCPLINT->localState->wanderingHeroes[index]);
return std::make_shared<CEmptyHeroItem>();
}
CHeroList::CHeroList(int size, Point position, std::string btnUp, std::string btnDown):
CList(size, position, btnUp, btnDown, LOCPLINT->wanderingHeroes.size(), 303, 304, std::bind(&CHeroList::createHeroItem, this, _1))
CList(size, position, btnUp, btnDown, LOCPLINT->localState->wanderingHeroes.size(), 303, 304, std::bind(&CHeroList::createHeroItem, this, _1))
{
}
void CHeroList::select(const CGHeroInstance * hero)
{
selectIndex(vstd::find_pos(LOCPLINT->wanderingHeroes, hero));
selectIndex(vstd::find_pos(LOCPLINT->localState->wanderingHeroes, hero));
}
void CHeroList::update(const CGHeroInstance * hero)
@ -245,7 +246,7 @@ void CHeroList::update(const CGHeroInstance * hero)
for(auto & elem : listBox->getItems())
{
auto item = std::dynamic_pointer_cast<CHeroItem>(elem);
if(item && item->hero == hero && vstd::contains(LOCPLINT->wanderingHeroes, hero))
if(item && item->hero == hero && vstd::contains(LOCPLINT->localState->wanderingHeroes, hero))
{
item->update();
return;
@ -253,7 +254,7 @@ void CHeroList::update(const CGHeroInstance * hero)
}
//simplest solution for now: reset list and restore selection
listBox->resize(LOCPLINT->wanderingHeroes.size());
listBox->resize(LOCPLINT->localState->wanderingHeroes.size());
if (adventureInt->getCurrentHero())
select(adventureInt->getCurrentHero());
@ -262,8 +263,8 @@ void CHeroList::update(const CGHeroInstance * hero)
std::shared_ptr<CIntObject> CTownList::createTownItem(size_t index)
{
if (LOCPLINT->towns.size() > index)
return std::make_shared<CTownItem>(this, LOCPLINT->towns[index]);
if (LOCPLINT->localState->ownedTowns.size() > index)
return std::make_shared<CTownItem>(this, LOCPLINT->localState->ownedTowns[index]);
return std::make_shared<CAnimImage>("ITPA", 0);
}
@ -312,20 +313,20 @@ std::string CTownList::CTownItem::getHoverText()
}
CTownList::CTownList(int size, Point position, std::string btnUp, std::string btnDown):
CList(size, position, btnUp, btnDown, LOCPLINT->towns.size(), 306, 307, std::bind(&CTownList::createTownItem, this, _1))
CList(size, position, btnUp, btnDown, LOCPLINT->localState->ownedTowns.size(), 306, 307, std::bind(&CTownList::createTownItem, this, _1))
{
}
void CTownList::select(const CGTownInstance * town)
{
selectIndex(vstd::find_pos(LOCPLINT->towns, town));
selectIndex(vstd::find_pos(LOCPLINT->localState->ownedTowns, town));
}
void CTownList::update(const CGTownInstance *)
{
//simplest solution for now: reset list and restore selection
listBox->resize(LOCPLINT->towns.size());
listBox->resize(LOCPLINT->localState->ownedTowns.size());
if (adventureInt->getCurrentTown())
select(adventureInt->getCurrentTown());

View File

@ -17,6 +17,7 @@
#include "../../CCallback.h"
#include "../CGameInfo.h"
#include "../CPlayerInterface.h"
#include "../PlayerLocalState.h"
#include "../adventureMap/CAdventureMapInterface.h"
#include "../../lib/CPathfinder.h"
@ -211,10 +212,10 @@ const CGPath * MapRendererAdventureContext::currentPath() const
if(!hero)
return nullptr;
if(!LOCPLINT->paths.hasPath(hero))
if(!LOCPLINT->localState->hasPath(hero))
return nullptr;
return &LOCPLINT->paths.getPath(hero);
return &LOCPLINT->localState->getPath(hero);
}
size_t MapRendererAdventureContext::objectImageIndex(ObjectInstanceID objectID, size_t groupSize) const

View File

@ -19,6 +19,7 @@
#include "../CGameInfo.h"
#include "../CMusicHandler.h"
#include "../CPlayerInterface.h"
#include "../PlayerLocalState.h"
#include "../gui/CGuiHandler.h"
#include "../widgets/MiscWidgets.h"
#include "../widgets/CComponent.h"
@ -1241,13 +1242,13 @@ void CCastleInterface::castleTeleport(int where)
const CGTownInstance * dest = LOCPLINT->cb->getTown(ObjectInstanceID(where));
adventureInt->setSelection(town->visitingHero);//according to assert(ho == adventureInt->selection) in the eraseCurrentPathOf
LOCPLINT->cb->teleportHero(town->visitingHero, dest);
LOCPLINT->paths.erasePath(town->visitingHero);
LOCPLINT->localState->erasePath(town->visitingHero);
}
void CCastleInterface::townChange()
{
//TODO: do not recreate window
const CGTownInstance * dest = LOCPLINT->towns[townlist->getSelectedIndex()];
const CGTownInstance * dest = LOCPLINT->localState->ownedTowns[townlist->getSelectedIndex()];
const CGTownInstance * town = this->town;// "this" is going to be deleted
if ( dest == town )
return;

View File

@ -18,6 +18,7 @@
#include "../CGameInfo.h"
#include "../CPlayerInterface.h"
#include "../PlayerLocalState.h"
#include "../CVideoHandler.h"
#include "../battle/BattleInterface.h"
@ -221,9 +222,9 @@ CSpellWindow::CSpellWindow(const CGHeroInstance * _myHero, CPlayerInterface * _m
}
}
selectedTab = battleSpellsOnly ? myInt->spellbookSettings.spellbookLastTabBattle : myInt->spellbookSettings.spellbookLastTabAdvmap;
selectedTab = battleSpellsOnly ? myInt->localState->spellbookSettings.spellbookLastTabBattle : myInt->localState->spellbookSettings.spellbookLastTabAdvmap;
schoolTab->setFrame(selectedTab, 0);
int cp = battleSpellsOnly ? myInt->spellbookSettings.spellbookLastPageBattle : myInt->spellbookSettings.spellbokLastPageAdvmap;
int cp = battleSpellsOnly ? myInt->localState->spellbookSettings.spellbookLastPageBattle : myInt->localState->spellbookSettings.spellbokLastPageAdvmap;
// spellbook last page battle index is not reset after battle, so this needs to stay here
vstd::abetween(cp, 0, std::max(0, pagesWithinCurrentTab() - 1));
setCurrentPage(cp);
@ -237,8 +238,8 @@ CSpellWindow::~CSpellWindow()
void CSpellWindow::fexitb()
{
(myInt->battleInt ? myInt->spellbookSettings.spellbookLastTabBattle : myInt->spellbookSettings.spellbookLastTabAdvmap) = selectedTab;
(myInt->battleInt ? myInt->spellbookSettings.spellbookLastPageBattle : myInt->spellbookSettings.spellbokLastPageAdvmap) = currentPage;
(myInt->battleInt ? myInt->localState->spellbookSettings.spellbookLastTabBattle : myInt->localState->spellbookSettings.spellbookLastTabAdvmap) = selectedTab;
(myInt->battleInt ? myInt->localState->spellbookSettings.spellbookLastPageBattle : myInt->localState->spellbookSettings.spellbokLastPageAdvmap) = currentPage;
close();
}
@ -556,8 +557,8 @@ void CSpellWindow::SpellArea::clickLeft(tribool down, bool previousState)
auto guard = vstd::makeScopeGuard([this]()
{
owner->myInt->spellbookSettings.spellbookLastTabAdvmap = owner->selectedTab;
owner->myInt->spellbookSettings.spellbokLastPageAdvmap = owner->currentPage;
owner->myInt->localState->spellbookSettings.spellbookLastTabAdvmap = owner->selectedTab;
owner->myInt->localState->spellbookSettings.spellbokLastPageAdvmap = owner->currentPage;
});
if(mySpell->getTargetType() == spells::AimType::LOCATION)