mirror of
				https://github.com/vcmi/vcmi.git
				synced 2025-10-31 00:07:39 +02:00 
			
		
		
		
	Moved player-specific heroes & towns information to new class
This commit is contained in:
		| @@ -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 | ||||
|   | ||||
| @@ -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) | ||||
|   | ||||
| @@ -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
									
								
							
							
						
						
									
										105
									
								
								client/PlayerLocalState.cpp
									
									
									
									
									
										Normal 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
									
								
							
							
						
						
									
										84
									
								
								client/PlayerLocalState.h
									
									
									
									
									
										Normal 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; | ||||
| 	} | ||||
| }; | ||||
| @@ -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); | ||||
| 			} | ||||
| 		} | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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()); | ||||
|  | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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; | ||||
|   | ||||
| @@ -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) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user