1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-20 20:23:03 +02:00

PlayerState now stores all objects owned by player

This commit is contained in:
Ivan Savenko 2024-08-24 22:21:26 +00:00
parent 0fd9dbf240
commit a481f07daf
21 changed files with 184 additions and 113 deletions

View File

@ -237,7 +237,7 @@ void CGameInfoCallback::getThievesGuildInfo(SThievesGuildInfo & thi, const CGObj
if(obj->ID == Obj::TOWN || obj->ID == Obj::TAVERN)
{
int taverns = 0;
for(auto town : gs->players[*getPlayerID()].towns)
for(auto town : gs->players[*getPlayerID()].getTowns())
{
if(town->hasBuilt(BuildingID::TAVERN))
taverns++;
@ -256,7 +256,7 @@ void CGameInfoCallback::getThievesGuildInfo(SThievesGuildInfo & thi, const CGObj
int CGameInfoCallback::howManyTowns(PlayerColor Player) const
{
ERROR_RET_VAL_IF(!hasAccess(Player), "Access forbidden!", -1);
return static_cast<int>(gs->players[Player].towns.size());
return static_cast<int>(gs->players[Player].getTowns().size());
}
bool CGameInfoCallback::getTownInfo(const CGObjectInstance * town, InfoAboutTown & dest, const CGObjectInstance * selectedObject) const
@ -609,7 +609,7 @@ EBuildingState CGameInfoCallback::canBuildStructure( const CGTownInstance *t, Bu
const PlayerState *ps = getPlayerState(t->tempOwner, false);
if(ps)
{
for(const CGTownInstance *town : ps->towns)
for(const CGTownInstance *town : ps->getTowns())
{
if(town->hasBuilt(BuildingID::CAPITOL))
{
@ -711,9 +711,9 @@ int CGameInfoCallback::getHeroCount( PlayerColor player, bool includeGarrisoned
ERROR_RET_VAL_IF(!p, "No such player!", -1);
if(includeGarrisoned)
return static_cast<int>(p->heroes.size());
return static_cast<int>(p->getHeroes().size());
else
for(const auto & elem : p->heroes)
for(const auto & elem : p->getHeroes())
if(!elem->inTownGarrison)
ret++;
return ret;
@ -757,7 +757,7 @@ std::vector < const CGTownInstance *> CPlayerSpecificInfoCallback::getTownsInfo(
auto ret = std::vector < const CGTownInstance *>();
for(const auto & i : gs->players)
{
for(const auto & town : i.second.towns)
for(const auto & town : i.second.getTowns())
{
if(i.first == getPlayerID() || (!onlyOur && isVisible(town, getPlayerID())))
{
@ -789,7 +789,7 @@ int CPlayerSpecificInfoCallback::getHeroSerial(const CGHeroInstance * hero, bool
return -1;
size_t index = 0;
auto & heroes = gs->players[*getPlayerID()].heroes;
const auto & heroes = gs->players[*getPlayerID()].getHeroes();
for (auto & possibleHero : heroes)
{
@ -835,7 +835,7 @@ std::vector < const CGDwelling * > CPlayerSpecificInfoCallback::getMyDwellings()
{
ASSERT_IF_CALLED_WITH_PLAYER
std::vector < const CGDwelling * > ret;
for(CGDwelling * dw : gs->getPlayerState(*getPlayerID())->dwellings)
for(const CGDwelling * dw : gs->getPlayerState(*getPlayerID())->getDwellings())
{
ret.push_back(dw);
}
@ -867,12 +867,12 @@ const CGHeroInstance* CPlayerSpecificInfoCallback::getHeroBySerial(int serialId,
if (!includeGarrisoned)
{
for(ui32 i = 0; i < p->heroes.size() && static_cast<int>(i) <= serialId; i++)
if(p->heroes[i]->inTownGarrison)
for(ui32 i = 0; i < p->getHeroes().size() && static_cast<int>(i) <= serialId; i++)
if(p->getHeroes()[i]->inTownGarrison)
serialId++;
}
ERROR_RET_VAL_IF(serialId < 0 || serialId >= p->heroes.size(), "No player info", nullptr);
return p->heroes[serialId];
ERROR_RET_VAL_IF(serialId < 0 || serialId >= p->getHeroes().size(), "No player info", nullptr);
return p->getHeroes()[serialId];
}
const CGTownInstance* CPlayerSpecificInfoCallback::getTownBySerial(int serialId) const
@ -880,8 +880,8 @@ const CGTownInstance* CPlayerSpecificInfoCallback::getTownBySerial(int serialId)
ASSERT_IF_CALLED_WITH_PLAYER
const PlayerState *p = getPlayerState(*getPlayerID());
ERROR_RET_VAL_IF(!p, "No player info", nullptr);
ERROR_RET_VAL_IF(serialId < 0 || serialId >= p->towns.size(), "No player info", nullptr);
return p->towns[serialId];
ERROR_RET_VAL_IF(serialId < 0 || serialId >= p->getTowns().size(), "No player info", nullptr);
return p->getTowns()[serialId];
}
int CPlayerSpecificInfoCallback::getResourceAmount(GameResID type) const

View File

@ -23,7 +23,7 @@ struct InfoWindow;
struct PlayerSettings;
struct CPackForClient;
struct TerrainTile;
struct PlayerState;
class PlayerState;
class CTown;
struct StartInfo;
struct CPathsInfo;

View File

@ -10,6 +10,9 @@
#include "StdInc.h"
#include "CPlayerState.h"
#include "mapObjects/CGDwelling.h"
#include "mapObjects/CGTownInstance.h"
#include "mapObjects/CGHeroInstance.h"
#include "gameState/QuestInfo.h"
#include "texts/CGeneralTextHandler.h"
#include "VCMI_Lib.h"
@ -90,4 +93,66 @@ int PlayerState::getResourceAmount(int type) const
return vstd::atOrDefault(resources, static_cast<size_t>(type), 0);
}
std::vector<const CGDwelling* > PlayerState::getDwellings() const
{
std::vector<const CGDwelling* > result;
for (auto const & object : ownedObjects)
{
auto dwelling = dynamic_cast<const CGDwelling *>(object);
auto town = dynamic_cast<const CGTownInstance *>(object);
if (dwelling && !town)
result.push_back(dwelling);
}
return result;
}
template<typename T>
std::vector<T> PlayerState::getObjectsOfType() const
{
std::vector<T> result;
for (auto const & object : ownedObjects)
{
auto casted = dynamic_cast<T>(object);
if (casted)
result.push_back(casted);
}
return result;
}
std::vector<const CGHeroInstance *> PlayerState::getHeroes() const
{
return getObjectsOfType<const CGHeroInstance *>();
}
std::vector<const CGTownInstance *> PlayerState::getTowns() const
{
return getObjectsOfType<const CGTownInstance *>();
}
std::vector<CGHeroInstance *> PlayerState::getHeroes()
{
return getObjectsOfType<CGHeroInstance *>();
}
std::vector<CGTownInstance *> PlayerState::getTowns()
{
return getObjectsOfType<CGTownInstance *>();
}
std::vector<const CGObjectInstance *> PlayerState::getOwnedObjects() const
{
return {ownedObjects.begin(), ownedObjects.end()};
}
void PlayerState::addOwnedObject(CGObjectInstance * object)
{
ownedObjects.push_back(object);
}
void PlayerState::removeOwnedObject(CGObjectInstance * object)
{
vstd::erase(ownedObjects, object);
}
VCMI_LIB_NAMESPACE_END

View File

@ -20,12 +20,13 @@
VCMI_LIB_NAMESPACE_BEGIN
class CGObjectInstance;
class CGHeroInstance;
class CGTownInstance;
class CGDwelling;
struct QuestInfo;
struct DLL_LINKAGE PlayerState : public CBonusSystemNode, public Player
class DLL_LINKAGE PlayerState : public CBonusSystemNode, public Player
{
struct VisitedObjectGlobal
{
@ -47,6 +48,11 @@ struct DLL_LINKAGE PlayerState : public CBonusSystemNode, public Player
}
};
std::vector<CGObjectInstance*> ownedObjects;
template<typename T>
std::vector<T> getObjectsOfType() const;
public:
PlayerColor color;
bool human; //true if human controlled player, false for AI
@ -55,12 +61,8 @@ public:
/// list of objects that were "destroyed" by player, either via simple pick-up (e.g. resources) or defeated heroes or wandering monsters
std::set<ObjectInstanceID> destroyedObjects;
std::set<ObjectInstanceID> visitedObjects; // as a std::set, since most accesses here will be from visited status checks
std::set<VisitedObjectGlobal> visitedObjectsGlobal;
std::vector<ConstTransitivePtr<CGHeroInstance> > heroes;
std::vector<ConstTransitivePtr<CGTownInstance> > towns;
std::vector<ConstTransitivePtr<CGDwelling> > dwellings; //used for town growth
std::vector<QuestInfo> quests; //store info about all received quests
std::vector<Bonus> battleBonuses; //additional bonuses to be added during battle with neutrals
std::map<uint32_t, std::map<ArtifactPosition, ArtifactID>> costumesArtifacts;
@ -90,9 +92,20 @@ public:
std::string getNameTextID() const override;
void registerIcons(const IconRegistar & cb) const override;
std::vector<const CGHeroInstance* > getHeroes() const;
std::vector<const CGTownInstance* > getTowns() const;
std::vector<CGHeroInstance* > getHeroes();
std::vector<CGTownInstance* > getTowns();
std::vector<const CGDwelling* > getDwellings() const;
std::vector<const CGObjectInstance* > getOwnedObjects() const;
void addOwnedObject(CGObjectInstance * object);
void removeOwnedObject(CGObjectInstance * object);
bool checkVanquished() const
{
return heroes.empty() && towns.empty();
return ownedObjects.empty();
}
template <typename Handler> void serialize(Handler &h)
@ -103,9 +116,10 @@ public:
h & resources;
h & status;
h & turnTimer;
h & heroes;
h & towns;
h & dwellings;
h & ownedObjects;
//h & heroes;
//h & towns;
//h & dwellings;
h & quests;
h & visitedObjects;
h & visitedObjectsGlobal;

View File

@ -574,7 +574,6 @@ void CGameState::initHeroes()
}
hero->initHero(getRandomGenerator());
getPlayerState(hero->getOwner())->heroes.push_back(hero);
map->allHeroes[hero->getHeroType().getNum()] = hero;
}
@ -699,14 +698,14 @@ void CGameState::initStartingBonus()
}
case PlayerStartingBonus::ARTIFACT:
{
if(elem.second.heroes.empty())
if(elem.second.getHeroes().empty())
{
logGlobal->error("Cannot give starting artifact - no heroes!");
break;
}
const Artifact * toGive = pickRandomArtifact(getRandomGenerator(), CArtifact::ART_TREASURE).toEntity(VLC);
CGHeroInstance *hero = elem.second.heroes[0];
CGHeroInstance *hero = elem.second.getHeroes()[0];
if(!giveHeroArtifact(hero, toGive->getId()))
logGlobal->error("Cannot give starting artifact - no free slots!");
}
@ -893,8 +892,6 @@ void CGameState::initTowns()
vti->possibleSpells -= s->id;
}
vti->possibleSpells.clear();
if(vti->getOwner() != PlayerColor::NEUTRAL)
getPlayerState(vti->getOwner())->towns.emplace_back(vti);
}
}
@ -902,6 +899,12 @@ void CGameState::initMapObjects()
{
logGlobal->debug("\tObject initialization");
for(CGObjectInstance *obj : map->objects)
{
if (obj && obj->getOwner().isValidPlayer())
getPlayerState(obj->getOwner())->addOwnedObject(obj);
}
// objCaller->preInit();
for(CGObjectInstance *obj : map->objects)
{
@ -937,9 +940,9 @@ void CGameState::placeHeroesInTowns()
if(player.first == PlayerColor::NEUTRAL)
continue;
for(CGHeroInstance * h : player.second.heroes)
for(CGHeroInstance * h : player.second.getHeroes())
{
for(CGTownInstance * t : player.second.towns)
for(CGTownInstance * t : player.second.getTowns())
{
if(h->visitablePos().z != t->visitablePos().z)
continue;
@ -971,9 +974,9 @@ void CGameState::initVisitingAndGarrisonedHeroes()
continue;
//init visiting and garrisoned heroes
for(CGHeroInstance * h : player.second.heroes)
for(CGHeroInstance * h : player.second.getHeroes())
{
for(CGTownInstance * t : player.second.towns)
for(CGTownInstance * t : player.second.getTowns())
{
if(h->visitablePos().z != t->visitablePos().z)
continue;
@ -1371,7 +1374,7 @@ bool CGameState::checkForVictory(const PlayerColor & player, const EventConditio
}
case EventCondition::HAVE_ARTIFACT: //check if any hero has winning artifact
{
for(const auto & elem : p->heroes)
for(const auto & elem : p->getHeroes())
if(elem->hasArt(condition.objectType.as<ArtifactID>()))
return true;
return false;
@ -1405,7 +1408,7 @@ bool CGameState::checkForVictory(const PlayerColor & player, const EventConditio
}
else // any town
{
for (const CGTownInstance * t : p->towns)
for (const CGTownInstance * t : p->getTowns())
{
if (t->hasBuilt(condition.objectType.as<BuildingID>()))
return true;
@ -1550,9 +1553,9 @@ void CGameState::obtainPlayersStats(SThievesGuildInfo & tgi, int level)
if(level >= 0) //num of towns & num of heroes
{
//num of towns
FILL_FIELD(numOfTowns, g->second.towns.size())
FILL_FIELD(numOfTowns, g->second.getTowns().size())
//num of heroes
FILL_FIELD(numOfHeroes, g->second.heroes.size())
FILL_FIELD(numOfHeroes, g->second.getHeroes().size())
}
if(level >= 1) //best hero's portrait
{
@ -1624,7 +1627,7 @@ void CGameState::obtainPlayersStats(SThievesGuildInfo & tgi, int level)
if(playerInactive(player.second.color)) //do nothing for neutral player
continue;
CreatureID bestCre; //best creature's ID
for(const auto & elem : player.second.heroes)
for(const auto & elem : player.second.getHeroes())
{
for(const auto & it : elem->Slots())
{

View File

@ -536,7 +536,7 @@ void CGameStateCampaign::initHeroes()
}
assert(humanPlayer != PlayerColor::NEUTRAL);
std::vector<ConstTransitivePtr<CGHeroInstance> > & heroes = gameState->players[humanPlayer].heroes;
const auto & heroes = gameState->players[humanPlayer].getHeroes();
if (chosenBonus->info1 == 0xFFFD) //most powerful
{

View File

@ -50,10 +50,10 @@ StatisticDataSetEntry StatisticDataSet::createEntry(const PlayerState * ps, cons
data.isHuman = ps->isHuman();
data.status = ps->status;
data.resources = ps->resources;
data.numberHeroes = ps->heroes.size();
data.numberHeroes = ps->getHeroes().size();
data.numberTowns = gs->howManyTowns(ps->color);
data.numberArtifacts = Statistic::getNumberOfArts(ps);
data.numberDwellings = gs->getPlayerState(ps->color)->dwellings.size();
data.numberDwellings = gs->getPlayerState(ps->color)->getDwellings().size();
data.armyStrength = Statistic::getArmyStrength(ps, true);
data.totalExperience = Statistic::getTotalExperience(ps);
data.income = Statistic::getIncome(gs, ps);
@ -221,7 +221,7 @@ std::vector<const CGMine *> Statistic::getMines(const CGameState * gs, const Pla
int Statistic::getNumberOfArts(const PlayerState * ps)
{
int ret = 0;
for(auto h : ps->heroes)
for(auto h : ps->getHeroes())
{
ret += h->artifactsInBackpack.size() + h->artifactsWorn.size();
}
@ -233,7 +233,7 @@ si64 Statistic::getArmyStrength(const PlayerState * ps, bool withTownGarrison)
{
si64 str = 0;
for(auto h : ps->heroes)
for(auto h : ps->getHeroes())
{
if(!h->inTownGarrison || withTownGarrison) //original h3 behavior
str += h->getArmyStrength();
@ -246,7 +246,7 @@ si64 Statistic::getTotalExperience(const PlayerState * ps)
{
si64 tmp = 0;
for(auto h : ps->heroes)
for(auto h : ps->getHeroes())
tmp += h->exp;
return tmp;
@ -258,11 +258,11 @@ int Statistic::getIncome(const CGameState * gs, const PlayerState * ps)
int totalIncome = 0;
//Heroes can produce gold as well - skill, specialty or arts
for(const auto & h : ps->heroes)
for(const auto & h : ps->getHeroes())
totalIncome += h->dailyIncome()[EGameResID::GOLD];
//Add town income of all towns
for(const auto & t : ps->towns)
for(const auto & t : ps->getTowns())
totalIncome += t->dailyIncome()[EGameResID::GOLD];
for(const CGMine * mine : getMines(gs, ps))
@ -295,7 +295,7 @@ float Statistic::getMapExploredRatio(const CGameState * gs, PlayerColor player)
const CGHeroInstance * Statistic::findBestHero(const CGameState * gs, const PlayerColor & color)
{
auto &h = gs->players.at(color).heroes;
const auto &h = gs->players.at(color).getHeroes();
if(h.empty())
return nullptr;
//best hero will be that with highest exp
@ -368,7 +368,7 @@ float Statistic::getTownBuiltRatio(const PlayerState * ps)
float built = 0.0;
float total = 0.0;
for(const auto & t : ps->towns)
for(const auto & t : ps->getTowns())
{
built += t->getBuildings().size();
for(const auto & b : t->town->buildings)

View File

@ -14,7 +14,7 @@
VCMI_LIB_NAMESPACE_BEGIN
struct PlayerState;
class PlayerState;
class CGameState;
class CGHeroInstance;
class CGMine;

View File

@ -29,10 +29,10 @@ HighScoreParameter HighScore::prepareHighScores(const CGameState * gs, PlayerCol
param.townAmount = gs->howManyTowns(player);
param.usedCheat = gs->getPlayerState(player)->cheated;
param.hasGrail = false;
for(const CGHeroInstance * h : playerState->heroes)
for(const CGHeroInstance * h : playerState->getHeroes())
if(h->hasArt(ArtifactID::GRAIL))
param.hasGrail = true;
for(const CGTownInstance * t : playerState->towns)
for(const CGTownInstance * t : playerState->getTowns())
if(t->hasBuilt(BuildingID::GRAIL))
param.hasGrail = true;
param.allEnemiesDefeated = true;

View File

@ -182,10 +182,6 @@ void CGDwelling::initObj(vstd::RNG & rand)
case Obj::CREATURE_GENERATOR4:
{
getObjectHandler()->configureObject(this, rand);
if (getOwner() != PlayerColor::NEUTRAL)
cb->gameState()->players[getOwner()].dwellings.emplace_back(this);
assert(!creatures.empty());
assert(!creatures[0].second.empty());
break;
@ -211,19 +207,6 @@ void CGDwelling::setPropertyDer(ObjProperty what, ObjPropertyID identifier)
{
switch (what)
{
case ObjProperty::OWNER: //change owner
if (ID == Obj::CREATURE_GENERATOR1 || ID == Obj::CREATURE_GENERATOR2
|| ID == Obj::CREATURE_GENERATOR3 || ID == Obj::CREATURE_GENERATOR4)
{
if (tempOwner != PlayerColor::NEUTRAL)
{
std::vector<ConstTransitivePtr<CGDwelling> >* dwellings = &cb->gameState()->players[tempOwner].dwellings;
dwellings->erase (std::find(dwellings->begin(), dwellings->end(), this));
}
if (identifier.as<PlayerColor>().isValidPlayer())
cb->gameState()->players[identifier.as<PlayerColor>()].dwellings.emplace_back(this);
}
break;
case ObjProperty::AVAILABLE_CREATURE:
creatures.resize(1);
creatures[0].second.resize(1);

View File

@ -181,7 +181,7 @@ GrowthInfo CGTownInstance::getGrowthInfo(int level) const
int dwellingBonus = 0;
if(const PlayerState *p = cb->getPlayerState(tempOwner, false))
{
dwellingBonus = getDwellingBonus(creatures[level].second, p->dwellings);
dwellingBonus = getDwellingBonus(creatures[level].second, p->getDwellings());
}
if(dwellingBonus)
ret.entries.emplace_back(VLC->generaltexth->allTexts[591], dwellingBonus); // \nExternal dwellings %+d
@ -192,7 +192,7 @@ GrowthInfo CGTownInstance::getGrowthInfo(int level) const
return ret;
}
int CGTownInstance::getDwellingBonus(const std::vector<CreatureID>& creatureIds, const std::vector<ConstTransitivePtr<CGDwelling> >& dwellings) const
int CGTownInstance::getDwellingBonus(const std::vector<CreatureID>& creatureIds, const std::vector<const CGDwelling * >& dwellings) const
{
int totalBonus = 0;
for (const auto& dwelling : dwellings)
@ -635,9 +635,9 @@ void CGTownInstance::removeCapitols(const PlayerColor & owner) const
if (hasCapitol()) // search if there's an older capitol
{
PlayerState* state = cb->gameState()->getPlayerState(owner); //get all towns owned by player
for (auto i = state->towns.cbegin(); i < state->towns.cend(); ++i)
for (const auto & town : state->getTowns())
{
if (*i != this && (*i)->hasCapitol())
if (town != this && town->hasCapitol())
{
RazeStructures rs;
rs.tid = id;
@ -672,7 +672,7 @@ int CGTownInstance::getMarketEfficiency() const
assert(p);
int marketCount = 0;
for(const CGTownInstance *t : p->towns)
for(const CGTownInstance *t : p->getTowns())
if(t->hasBuiltSomeTradeBuilding())
marketCount++;

View File

@ -239,7 +239,7 @@ private:
FactionID randomizeFaction(vstd::RNG & rand);
void setOwner(const PlayerColor & owner) const;
void onTownCaptured(const PlayerColor & winner) const;
int getDwellingBonus(const std::vector<CreatureID>& creatureIds, const std::vector<ConstTransitivePtr<CGDwelling> >& dwellings) const;
int getDwellingBonus(const std::vector<CreatureID>& creatureIds, const std::vector<const CGDwelling* >& dwellings) const;
bool townEnvisagesBuilding(BuildingSubID::EBuildingSubID bid) const;
void initializeConfigurableBuildings(vstd::RNG & rand);
};

View File

@ -1171,7 +1171,7 @@ void RemoveObject::applyGs(CGameState *gs)
assert(beatenHero);
PlayerState * p = gs->getPlayerState(beatenHero->tempOwner);
gs->map->heroesOnMap -= beatenHero;
p->heroes -= beatenHero;
p->removeOwnedObject(beatenHero);
auto * siegeNode = beatenHero->whereShouldBeAttachedOnSiege(gs);
@ -1417,7 +1417,7 @@ void HeroRecruited::applyGs(CGameState *gs)
gs->map->objects[h->id.getNum()] = h;
gs->map->heroesOnMap.emplace_back(h);
p->heroes.emplace_back(h);
p->addOwnedObject(h);
h->attachTo(*p);
gs->map->addBlockVisTiles(h);
@ -1452,7 +1452,7 @@ void GiveHero::applyGs(CGameState *gs)
h->setMovementPoints(h->movementPointsLimit(true));
h->pos = h->convertFromVisitablePos(oldVisitablePos);
gs->map->heroesOnMap.emplace_back(h);
gs->getPlayerState(h->getOwner())->heroes.emplace_back(h);
gs->getPlayerState(h->getOwner())->addOwnedObject(h);
gs->map->addBlockVisTiles(h);
h->inTownGarrison = false;
@ -1942,6 +1942,18 @@ void SetObjectProperty::applyGs(CGameState *gs)
}
auto * cai = dynamic_cast<CArmedInstance *>(obj);
if(what == ObjProperty::OWNER)
{
PlayerColor oldOwner = obj->getOwner();
PlayerColor newOwner = identifier.as<PlayerColor>();
if(oldOwner.isValidPlayer())
gs->getPlayerState(oldOwner)->removeOwnedObject(obj);;
if(newOwner.isValidPlayer())
gs->getPlayerState(newOwner)->addOwnedObject(obj);;
}
if(what == ObjProperty::OWNER && cai)
{
if(obj->ID == Obj::TOWN)
@ -1953,17 +1965,13 @@ void SetObjectProperty::applyGs(CGameState *gs)
if(oldOwner.isValidPlayer())
{
auto * state = gs->getPlayerState(oldOwner);
state->towns -= t;
if(state->towns.empty())
if(state->getTowns().empty())
state->daysWithoutCastle = 0;
}
if(identifier.as<PlayerColor>().isValidPlayer())
{
PlayerState * p = gs->getPlayerState(identifier.as<PlayerColor>());
p->towns.emplace_back(t);
//reset counter before NewTurn to avoid no town message if game loaded at turn when one already captured
PlayerState * p = gs->getPlayerState(identifier.as<PlayerColor>());
if(p->daysWithoutCastle)
p->daysWithoutCastle = std::nullopt;
}

View File

@ -264,8 +264,7 @@ TeleporterTilesVector CPathfinderHelper::getCastleGates(const PathNodeInfo & sou
{
TeleporterTilesVector allowedExits;
auto towns = getPlayerState(hero->tempOwner)->towns;
for(const auto & town : towns)
for(const auto & town : getPlayerState(hero->tempOwner)->getTowns())
{
if(town->id != source.nodeObject->id && town->visitingHero == nullptr
&& town->hasBuilt(BuildingID::CASTLE_GATE, ETownType::INFERNO))

View File

@ -692,9 +692,9 @@ std::vector <const CGTownInstance*> TownPortalMechanics::getPossibleTowns(SpellC
for(const auto & color : team->players)
{
for(auto currTown : env->getCb()->getPlayerState(color)->towns)
for(auto currTown : env->getCb()->getPlayerState(color)->getTowns())
{
ret.push_back(currTown.get());
ret.push_back(currTown);
}
}
return ret;

View File

@ -555,7 +555,7 @@ void CGameHandler::setPortalDwelling(const CGTownInstance * town, bool forced=fa
ssi.creatures = town->creatures;
ssi.creatures[town->town->creatures.size()].second.clear();//remove old one
const std::vector<ConstTransitivePtr<CGDwelling> > &dwellings = p->dwellings;
const auto &dwellings = p->getDwellings();
if (dwellings.empty())//no dwellings - just remove
{
sendAndApply(&ssi);
@ -639,7 +639,7 @@ void CGameHandler::onNewTurn()
if (player.second.status != EPlayerStatus::INGAME)
continue;
if (player.second.heroes.empty() && player.second.towns.empty())
if (player.second.getHeroes().empty() && player.second.getTowns().empty())
throw std::runtime_error("Invalid player in player state! Player " + std::to_string(player.first.getNum()) + ", map name: " + gs->map->name.toString() + ", map description: " + gs->map->description.toString());
}
@ -724,7 +724,7 @@ void CGameHandler::onNewTurn()
if (firstTurn)
heroPool->onNewWeek(elem.first);
for (CGHeroInstance *h : (elem).second.heroes)
for (CGHeroInstance *h : (elem).second.getHeroes())
{
if (h->visitedTown)
giveSpells(h->visitedTown, h);
@ -1286,9 +1286,9 @@ void CGameHandler::setOwner(const CGObjectInstance * obj, const PlayerColor owne
const PlayerState * p = getPlayerState(owner);
if ((obj->ID == Obj::CREATURE_GENERATOR1 || obj->ID == Obj::CREATURE_GENERATOR4) && p && p->dwellings.size()==1)//first dwelling captured
if ((obj->ID == Obj::CREATURE_GENERATOR1 || obj->ID == Obj::CREATURE_GENERATOR4) && p && p->getDwellings().size()==1)//first dwelling captured
{
for (const CGTownInstance * t : getPlayerState(owner)->towns)
for (const CGTownInstance * t : getPlayerState(owner)->getTowns())
{
if (t->hasBuilt(BuildingSubID::PORTAL_OF_SUMMONING))
setPortalDwelling(t);//set initial creatures for all portals of summoning
@ -3297,7 +3297,7 @@ void CGameHandler::handleTimeEvents(PlayerColor color)
}
}
void CGameHandler::handleTownEvents(CGTownInstance * town)
void CGameHandler::handleTownEvents(const CGTownInstance * town)
{
for (auto const & event : town->events)
{
@ -3631,10 +3631,10 @@ void CGameHandler::checkVictoryLossConditionsForPlayer(PlayerColor player)
else
{
//copy heroes vector to avoid iterator invalidation as removal change PlayerState
auto hlp = p->heroes;
auto hlp = p->getHeroes();
for (auto h : hlp) //eliminate heroes
{
if (h.get())
if (h)
removeObject(h, player);
}
@ -4159,11 +4159,11 @@ void CGameHandler::changeFogOfWar(int3 center, ui32 radius, PlayerColor player,
std::unordered_set<int3> observedTiles; //do not hide tiles observed by heroes. May lead to disastrous AI problems
auto p = getPlayerState(player);
for (auto h : p->heroes)
for (auto h : p->getHeroes())
{
getTilesInRange(observedTiles, h->getSightCenter(), h->getSightRadius(), ETileVisibility::REVEALED, h->tempOwner);
}
for (auto t : p->towns)
for (auto t : p->getTowns())
{
getTilesInRange(observedTiles, t->getSightCenter(), t->getSightRadius(), ETileVisibility::REVEALED, t->tempOwner);
}

View File

@ -230,7 +230,7 @@ public:
void addStatistics(StatisticDataSet &stat) const;
void handleTimeEvents(PlayerColor player);
void handleTownEvents(CGTownInstance *town);
void handleTownEvents(const CGTownInstance *town);
bool complain(const std::string &problem); //sends message to all clients, prints on the logs and return true
void objectVisited( const CGObjectInstance * obj, const CGHeroInstance * h );
void objectVisitEnded(const CObjectVisitQuery &query);

View File

@ -484,7 +484,7 @@ void BattleResultProcessor::endBattleConfirm(const CBattleInfoCallback & battle)
if(!finishingBattle->isDraw())
{
ConstTransitivePtr<CGHeroInstance> strongestHero = nullptr;
for(auto & hero : gameHandler->gameState()->getPlayerState(finishingBattle->loser)->heroes)
for(auto & hero : gameHandler->gameState()->getPlayerState(finishingBattle->loser)->getHeroes())
if(!strongestHero || hero->exp > strongestHero->exp)
strongestHero = hero;
if(strongestHero->id == finishingBattle->loserHero->id && strongestHero->level > 5)

View File

@ -40,10 +40,10 @@ void NewTurnProcessor::onPlayerTurnStarted(PlayerColor which)
const auto * playerState = gameHandler->gameState()->getPlayerState(which);
gameHandler->handleTimeEvents(which);
for (auto t : playerState->towns)
for (const auto * t : playerState->getTowns())
gameHandler->handleTownEvents(t);
for (auto t : playerState->towns)
for (const auto * t : playerState->getTowns())
{
//garrison hero first - consistent with original H3 Mana Vortex and Battle Scholar Academy levelup windows order
if (t->garrisonHero != nullptr)
@ -59,7 +59,7 @@ void NewTurnProcessor::onPlayerTurnEnded(PlayerColor which)
const auto * playerState = gameHandler->gameState()->getPlayerState(which);
assert(playerState->status == EPlayerStatus::INGAME);
if (playerState->towns.empty())
if (playerState->getTowns().empty())
{
DaysWithoutTown pack;
pack.player = which;
@ -92,7 +92,7 @@ ResourceSet NewTurnProcessor::generatePlayerIncome(PlayerColor playerID, bool ne
const PlayerState & state = gameHandler->gameState()->players.at(playerID);
ResourceSet income;
for (const auto & town : state.towns)
for (const auto & town : state.getTowns())
{
if (newWeek && town->hasBuilt(BuildingSubID::TREASURY))
{
@ -123,18 +123,18 @@ ResourceSet NewTurnProcessor::generatePlayerIncome(PlayerColor playerID, bool ne
for (GameResID k = GameResID::WOOD; k < GameResID::COUNT; k++)
{
income += state.valOfBonuses(BonusType::RESOURCES_CONSTANT_BOOST, BonusSubtypeID(k));
income += state.valOfBonuses(BonusType::RESOURCES_TOWN_MULTIPLYING_BOOST, BonusSubtypeID(k)) * state.towns.size();
income += state.valOfBonuses(BonusType::RESOURCES_TOWN_MULTIPLYING_BOOST, BonusSubtypeID(k)) * state.getTowns().size();
}
if(newWeek) //weekly crystal generation if 1 or more crystal dragons in any hero army or town garrison
{
bool hasCrystalGenCreature = false;
for (const auto & hero : state.heroes)
for (const auto & hero : state.getHeroes())
for(auto stack : hero->stacks)
if(stack.second->hasBonusOfType(BonusType::SPECIAL_CRYSTAL_GENERATION))
hasCrystalGenCreature = true;
for(const auto & town : state.towns)
for(const auto & town : state.getTowns())
for(auto stack : town->stacks)
if(stack.second->hasBonusOfType(BonusType::SPECIAL_CRYSTAL_GENERATION))
hasCrystalGenCreature = true;
@ -146,10 +146,9 @@ ResourceSet NewTurnProcessor::generatePlayerIncome(PlayerColor playerID, bool ne
TResources incomeHandicapped = income;
incomeHandicapped.applyHandicap(playerSettings->handicap.percentIncome);
// FIXME: store pre-filtered, all owned objects in PlayerState
for (auto obj : gameHandler->gameState()->map->objects)
for (auto obj : state.getOwnedObjects())
{
if (obj && obj->asOwnable() && obj->getOwner() == playerID)
if (obj->asOwnable())
incomeHandicapped += obj->asOwnable()->dailyIncome();
}

View File

@ -710,11 +710,11 @@ bool PlayerMessageProcessor::handleCheatCode(const std::string & cheat, PlayerCo
executeCheatCode(cheatName, i.first, ObjectInstanceID::NONE, parameters);
if (vstd::contains(townTargetedCheats, cheatName))
for (const auto & t : i.second.towns)
for (const auto & t : i.second.getTowns())
executeCheatCode(cheatName, i.first, t->id, parameters);
if (vstd::contains(heroTargetedCheats, cheatName))
for (const auto & h : i.second.heroes)
for (const auto & h : i.second.getHeroes())
executeCheatCode(cheatName, i.first, h->id, parameters);
}

View File

@ -121,7 +121,7 @@ bool TurnOrderProcessor::playersInContact(PlayerColor left, PlayerColor right) c
}
}
for(const auto & hero : leftInfo->heroes)
for(const auto & hero : leftInfo->getHeroes())
{
CPathsInfo out(mapSize, hero);
auto config = std::make_shared<SingleHeroPathfinderConfig>(out, gameHandler->gameState(), hero);
@ -137,7 +137,7 @@ bool TurnOrderProcessor::playersInContact(PlayerColor left, PlayerColor right) c
leftReachability[z][x][y] = true;
}
for(const auto & hero : rightInfo->heroes)
for(const auto & hero : rightInfo->getHeroes())
{
CPathsInfo out(mapSize, hero);
auto config = std::make_shared<SingleHeroPathfinderConfig>(out, gameHandler->gameState(), hero);