1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-05-31 22:59:54 +02:00

Remove ConstTransitivePtr from hero and town instances

This commit is contained in:
Ivan Savenko 2025-03-09 21:51:33 +00:00
parent 62234fcf92
commit 417ea6451a
57 changed files with 436 additions and 390 deletions

View File

@ -904,19 +904,19 @@ void AIGateway::performObjectInteraction(const CGObjectInstance * obj, HeroPtr h
switch(obj->ID)
{
case Obj::TOWN:
if(h->visitedTown) //we are inside, not just attacking
if(h->getVisitedTown()) //we are inside, not just attacking
{
makePossibleUpgrades(h.get());
std::unique_lock lockGuard(nullkiller->aiStateMutex);
if(!h->visitedTown->garrisonHero || !nullkiller->isHeroLocked(h->visitedTown->garrisonHero))
moveCreaturesToHero(h->visitedTown);
if(!h->getVisitedTown()->getGarrisonHero() || !nullkiller->isHeroLocked(h->getVisitedTown()->getGarrisonHero()))
moveCreaturesToHero(h->getVisitedTown());
if(nullkiller->heroManager->getHeroRole(h) == HeroRole::MAIN && !h->hasSpellbook()
&& nullkiller->getFreeGold() >= GameConstants::SPELLBOOK_GOLD_COST)
{
if(h->visitedTown->hasBuilt(BuildingID::MAGES_GUILD_1))
if(h->getVisitedTown()->hasBuilt(BuildingID::MAGES_GUILD_1))
cb->buyArtifact(h.get(), ArtifactID::SPELLBOOK);
}
}
@ -929,9 +929,9 @@ void AIGateway::performObjectInteraction(const CGObjectInstance * obj, HeroPtr h
void AIGateway::moveCreaturesToHero(const CGTownInstance * t)
{
if(t->visitingHero && t->armedGarrison() && t->visitingHero->tempOwner == t->tempOwner)
if(t->getVisitingHero() && t->armedGarrison() && t->getVisitingHero()->tempOwner == t->tempOwner)
{
pickBestCreatures(t->visitingHero, t->getUpperArmy());
pickBestCreatures(t->getVisitingHero(), t->getUpperArmy());
}
}
@ -1282,10 +1282,10 @@ void AIGateway::addVisitableObj(const CGObjectInstance * obj)
bool AIGateway::moveHeroToTile(int3 dst, HeroPtr h)
{
if(h->inTownGarrison && h->visitedTown)
if(h->isGarrisoned() && h->getVisitedTown())
{
cb->swapGarrisonHero(h->visitedTown);
moveCreaturesToHero(h->visitedTown);
cb->swapGarrisonHero(h->getVisitedTown());
moveCreaturesToHero(h->getVisitedTown());
}
//TODO: consider if blockVisit objects change something in our checks: AIUtility::isBlockVisitObj()
@ -1596,7 +1596,7 @@ void AIGateway::endTurn()
void AIGateway::buildArmyIn(const CGTownInstance * t)
{
makePossibleUpgrades(t->visitingHero);
makePossibleUpgrades(t->getVisitingHero());
makePossibleUpgrades(t);
recruitCreatures(t, t->getUpperArmy());
moveCreaturesToHero(t);

View File

@ -767,7 +767,7 @@ bool shouldVisit(const Nullkiller * ai, const CGHeroInstance * h, const CGObject
bool townHasFreeTavern(const CGTownInstance * town)
{
if(!town->hasBuilt(BuildingID::TAVERN)) return false;
if(!town->visitingHero) return true;
if(!town->getVisitingHero()) return true;
bool canMoveVisitingHeroToGarrison = !town->getUpperArmy()->stacksCount();
@ -778,9 +778,9 @@ uint64_t getHeroArmyStrengthWithCommander(const CGHeroInstance * hero, const CCr
{
auto armyStrength = heroArmy->getArmyStrength(fortLevel);
if(hero && hero->commander && hero->commander->alive)
if(hero && hero->getCommander() && hero->getCommander()->alive)
{
armyStrength += 100 * hero->commander->level;
armyStrength += 100 * hero->getCommander()->level;
}
return armyStrength;

View File

@ -93,8 +93,8 @@ void DangerHitMapAnalyzer::updateHitMap()
{
auto town = dynamic_cast<const CGTownInstance *>(obj);
if(town->garrisonHero)
heroes[town->garrisonHero->tempOwner][town->garrisonHero] = HeroRole::MAIN;
if(town->getGarrisonHero())
heroes[town->getGarrisonHero()->tempOwner][town->getGarrisonHero()] = HeroRole::MAIN;
}
}

View File

@ -293,7 +293,7 @@ const CGHeroInstance * HeroManager::findWeakHeroToDismiss(uint64_t armyLimit, co
|| existingHero->getArmyStrength() >armyLimit
|| getHeroRole(existingHero) == HeroRole::MAIN
|| existingHero->movementPointsRemaining()
|| (townToSpare != nullptr && existingHero->visitedTown == townToSpare)
|| (townToSpare != nullptr && existingHero->getVisitedTown() == townToSpare)
|| existingHero->artifactsWorn.size() > (existingHero->hasSpellbook() ? 2 : 1))
{
continue;

View File

@ -109,30 +109,30 @@ void handleCounterAttack(
bool handleGarrisonHeroFromPreviousTurn(const CGTownInstance * town, Goals::TGoalVec & tasks, const Nullkiller * ai)
{
if(ai->isHeroLocked(town->garrisonHero.get()))
if(ai->isHeroLocked(town->getGarrisonHero()))
{
logAi->trace(
"Hero %s in garrison of town %s is supposed to defend the town",
town->garrisonHero->getNameTranslated(),
town->getGarrisonHero()->getNameTranslated(),
town->getNameTranslated());
return true;
}
if(!town->visitingHero)
if(!town->getVisitingHero())
{
if(ai->cb->getHeroCount(ai->playerID, false) < GameConstants::MAX_HEROES_PER_PLAYER)
{
logAi->trace(
"Extracting hero %s from garrison of town %s",
town->garrisonHero->getNameTranslated(),
town->getGarrisonHero()->getNameTranslated(),
town->getNameTranslated());
tasks.push_back(Goals::sptr(Goals::ExchangeSwapTownHeroes(town, nullptr).setpriority(5)));
return false;
}
else if(ai->heroManager->getHeroRole(town->garrisonHero.get()) == HeroRole::MAIN)
else if(ai->heroManager->getHeroRole(town->getGarrisonHero()) == HeroRole::MAIN)
{
auto armyDismissLimit = 1000;
auto heroToDismiss = ai->heroManager->findWeakHeroToDismiss(armyDismissLimit);
@ -160,7 +160,7 @@ void DefenceBehavior::evaluateDefence(Goals::TGoalVec & tasks, const CGTownInsta
threats.push_back(threatNode.fastestDanger); // no guarantee that fastest danger will be there
if (town->garrisonHero && handleGarrisonHeroFromPreviousTurn(town, tasks, ai))
if (town->getGarrisonHero() && handleGarrisonHeroFromPreviousTurn(town, tasks, ai))
{
return;
}
@ -233,16 +233,16 @@ void DefenceBehavior::evaluateDefence(Goals::TGoalVec & tasks, const CGTownInsta
path.toString());
#endif
auto townDefenseStrength = town->garrisonHero
? town->garrisonHero->getTotalStrength()
: (town->visitingHero ? town->visitingHero->getTotalStrength() : town->getUpperArmy()->getArmyStrength());
auto townDefenseStrength = town->getGarrisonHero()
? town->getGarrisonHero()->getTotalStrength()
: (town->getVisitingHero() ? town->getVisitingHero()->getTotalStrength() : town->getUpperArmy()->getArmyStrength());
if(town->visitingHero && path.targetHero == town->visitingHero.get())
if(town->getVisitingHero() && path.targetHero == town->getVisitingHero())
{
if(path.getHeroStrength() < townDefenseStrength)
continue;
}
else if(town->garrisonHero && path.targetHero == town->garrisonHero.get())
else if(town->getGarrisonHero() && path.targetHero == town->getGarrisonHero())
{
if(path.getHeroStrength() < townDefenseStrength)
continue;
@ -271,7 +271,7 @@ void DefenceBehavior::evaluateDefence(Goals::TGoalVec & tasks, const CGTownInsta
continue;
}
if(path.targetHero == town->visitingHero.get() && path.exchangeCount == 1)
if(path.targetHero == town->getVisitingHero() && path.exchangeCount == 1)
{
#if NKAI_TRACE_LEVEL >= 1
logAi->trace("Put %s to garrison of town %s",
@ -280,7 +280,7 @@ void DefenceBehavior::evaluateDefence(Goals::TGoalVec & tasks, const CGTownInsta
#endif
// dismiss creatures we are not able to pick to be able to hide in garrison
if(town->garrisonHero
if(town->getGarrisonHero()
|| town->getUpperArmy()->stacksCount() == 0
|| path.targetHero->canBeMergedWith(*town)
|| (town->getUpperArmy()->getArmyStrength() < 500 && town->fortLevel() >= CGTownInstance::CITADEL))
@ -288,25 +288,25 @@ void DefenceBehavior::evaluateDefence(Goals::TGoalVec & tasks, const CGTownInsta
tasks.push_back(
Goals::sptr(Composition()
.addNext(DefendTown(town, threat, path.targetHero))
.addNext(ExchangeSwapTownHeroes(town, town->visitingHero.get(), HeroLockedReason::DEFENCE))));
.addNext(ExchangeSwapTownHeroes(town, town->getVisitingHero(), HeroLockedReason::DEFENCE))));
}
continue;
}
// main without army and visiting scout with army, very specific case
if(town->visitingHero && town->getUpperArmy()->stacksCount() == 0
&& path.targetHero != town->visitingHero.get() && path.exchangeCount == 1 && path.turn() == 0
&& ai->heroManager->evaluateHero(path.targetHero) > ai->heroManager->evaluateHero(town->visitingHero.get())
&& 10 * path.targetHero->getTotalStrength() < town->visitingHero->getTotalStrength())
if(town->getVisitingHero() && town->getUpperArmy()->stacksCount() == 0
&& path.targetHero != town->getVisitingHero() && path.exchangeCount == 1 && path.turn() == 0
&& ai->heroManager->evaluateHero(path.targetHero) > ai->heroManager->evaluateHero(town->getVisitingHero())
&& 10 * path.targetHero->getTotalStrength() < town->getVisitingHero()->getTotalStrength())
{
path.heroArmy = town->visitingHero.get();
path.heroArmy = town->getVisitingHero();
tasks.push_back(
Goals::sptr(Composition()
.addNext(DefendTown(town, threat, path))
.addNextSequence({
sptr(ExchangeSwapTownHeroes(town, town->visitingHero.get())),
sptr(ExchangeSwapTownHeroes(town, town->getVisitingHero())),
sptr(ExecuteHeroChain(path, town)),
sptr(ExchangeSwapTownHeroes(town, path.targetHero, HeroLockedReason::DEFENCE))
})));
@ -350,22 +350,22 @@ void DefenceBehavior::evaluateDefence(Goals::TGoalVec & tasks, const CGTownInsta
composition.addNext(DefendTown(town, threat, path));
TGoalVec sequence;
if(town->garrisonHero && path.targetHero == town->garrisonHero.get() && path.exchangeCount == 1)
if(town->getGarrisonHero() && path.targetHero == town->getGarrisonHero() && path.exchangeCount == 1)
{
composition.addNext(ExchangeSwapTownHeroes(town, town->garrisonHero.get(), HeroLockedReason::DEFENCE));
composition.addNext(ExchangeSwapTownHeroes(town, town->getGarrisonHero(), HeroLockedReason::DEFENCE));
tasks.push_back(Goals::sptr(composition));
#if NKAI_TRACE_LEVEL >= 1
logAi->trace("Locking hero %s in garrison of %s",
town->garrisonHero.get()->getObjectName(),
town->getGarrisonHero()->getObjectName(),
town->getObjectName());
#endif
continue;
}
else if(town->visitingHero && path.targetHero != town->visitingHero && !path.containsHero(town->visitingHero))
else if(town->getVisitingHero() && path.targetHero != town->getVisitingHero() && !path.containsHero(town->getVisitingHero()))
{
if(town->garrisonHero && town->garrisonHero != path.targetHero)
if(town->getGarrisonHero() && town->getGarrisonHero() != path.targetHero)
{
#if NKAI_TRACE_LEVEL >= 1
logAi->trace("Cancel moving %s to defend town %s as the town has garrison hero",
@ -376,7 +376,7 @@ void DefenceBehavior::evaluateDefence(Goals::TGoalVec & tasks, const CGTownInsta
}
else if(path.turn() == 0)
{
sequence.push_back(sptr(ExchangeSwapTownHeroes(town, town->visitingHero.get())));
sequence.push_back(sptr(ExchangeSwapTownHeroes(town, town->getVisitingHero())));
}
}
@ -425,7 +425,7 @@ void DefenceBehavior::evaluateDefence(Goals::TGoalVec & tasks, const CGTownInsta
void DefenceBehavior::evaluateRecruitingHero(Goals::TGoalVec & tasks, const HitMapInfo & threat, const CGTownInstance * town, const Nullkiller * ai) const
{
if (threat.turn > 0 || town->garrisonHero || town->visitingHero)
if (threat.turn > 0 || town->getGarrisonHero() || town->getVisitingHero())
return;
if(town->hasBuilt(BuildingID::TAVERN)
@ -461,25 +461,25 @@ void DefenceBehavior::evaluateRecruitingHero(Goals::TGoalVec & tasks, const HitM
bool needSwap = false;
const CGHeroInstance * heroToDismiss = nullptr;
if(town->visitingHero)
if(town->getVisitingHero())
{
if(!town->garrisonHero)
if(!town->getGarrisonHero())
needSwap = true;
else
{
if(town->visitingHero->getArmyStrength() < town->garrisonHero->getArmyStrength())
if(town->getVisitingHero()->getArmyStrength() < town->getGarrisonHero()->getArmyStrength())
{
if(town->visitingHero->getArmyStrength() >= hero->getArmyStrength())
if(town->getVisitingHero()->getArmyStrength() >= hero->getArmyStrength())
continue;
heroToDismiss = town->visitingHero.get();
heroToDismiss = town->getVisitingHero();
}
else if(town->garrisonHero->getArmyStrength() >= hero->getArmyStrength())
else if(town->getGarrisonHero()->getArmyStrength() >= hero->getArmyStrength())
continue;
else
{
needSwap = true;
heroToDismiss = town->garrisonHero.get();
heroToDismiss = town->getGarrisonHero();
}
}
@ -499,7 +499,7 @@ void DefenceBehavior::evaluateRecruitingHero(Goals::TGoalVec & tasks, const HitM
Goals::Composition recruitHeroComposition;
if(needSwap)
sequence.push_back(sptr(ExchangeSwapTownHeroes(town, town->visitingHero.get())));
sequence.push_back(sptr(ExchangeSwapTownHeroes(town, town->getVisitingHero())));
if(heroToDismiss)
sequence.push_back(sptr(DismissHero(heroToDismiss)));

View File

@ -167,21 +167,21 @@ Goals::TGoalVec GatherArmyBehavior::deliverArmyToHero(const Nullkiller * ai, con
composition.addNext(heroExchange);
if(hero->inTownGarrison && path.turn() == 0)
if(hero->isGarrisoned() && path.turn() == 0)
{
auto lockReason = ai->getHeroLockedReason(hero);
if(path.targetHero->visitedTown == hero->visitedTown)
if(path.targetHero->getVisitedTown() == hero->getVisitedTown())
{
composition.addNextSequence({
sptr(ExchangeSwapTownHeroes(hero->visitedTown, hero, lockReason))});
sptr(ExchangeSwapTownHeroes(hero->getVisitedTown(), hero, lockReason))});
}
else
{
composition.addNextSequence({
sptr(ExchangeSwapTownHeroes(hero->visitedTown)),
sptr(ExchangeSwapTownHeroes(hero->getVisitedTown())),
sptr(exchangePath),
sptr(ExchangeSwapTownHeroes(hero->visitedTown, hero, lockReason))});
sptr(ExchangeSwapTownHeroes(hero->getVisitedTown(), hero, lockReason))});
}
}
else
@ -262,7 +262,7 @@ Goals::TGoalVec GatherArmyBehavior::upgradeArmy(const Nullkiller * ai, const CGT
continue;
}
if(upgrader->visitingHero && (upgrader->visitingHero.get() != path.targetHero || path.exchangeCount == 1))
if(upgrader->getVisitingHero() && (upgrader->getVisitingHero() != path.targetHero || path.exchangeCount == 1))
{
#if NKAI_TRACE_LEVEL >= 2
logAi->trace("Ignore path. Town has visiting hero.");
@ -289,7 +289,7 @@ Goals::TGoalVec GatherArmyBehavior::upgradeArmy(const Nullkiller * ai, const CGT
auto upgrade = ai->armyManager->calculateCreaturesUpgrade(path.heroArmy, upgrader, availableResources);
if(!upgrader->garrisonHero
if(!upgrader->getGarrisonHero()
&& (
hasMainAround
|| ai->heroManager->getHeroRole(path.targetHero) == HeroRole::MAIN))

View File

@ -68,7 +68,7 @@ Goals::TGoalVec RecruitHeroBehavior::decompose(const Nullkiller * ai) const
closestThreat = std::min(closestThreat, threat.turn);
}
//Don't hire a hero where there already is one present
if (town->visitingHero && town->garrisonHero)
if (town->getVisitingHero() && town->getGarrisonHero())
continue;
float visitability = 0;
for (auto checkHero : ourHeroes)
@ -98,7 +98,7 @@ Goals::TGoalVec RecruitHeroBehavior::decompose(const Nullkiller * ai) const
for(auto hero : availableHeroes)
{
if ((town->visitingHero || town->garrisonHero)
if ((town->getVisitingHero() || town->getGarrisonHero())
&& closestThreat < 1
&& hero->getArmyCost() < GameConstants::HERO_GOLD_COST / 3.0)
continue;

View File

@ -32,7 +32,7 @@ const AIPath getShortestPath(const CGTownInstance * town, const std::vector<AIPa
{
auto shortestPath = *vstd::minElementByFun(paths, [town](const AIPath & path) -> float
{
if(town->garrisonHero && path.targetHero == town->garrisonHero.get())
if(town->getGarrisonHero() && path.targetHero == town->getGarrisonHero())
return 1;
return path.movementCost();
@ -53,7 +53,7 @@ const CGHeroInstance * getNearestHero(const Nullkiller * ai, const CGTownInstanc
if(shortestPath.nodes.size() > 1
|| shortestPath.turn() != 0
|| shortestPath.targetHero->visitablePos().dist2dSQ(town->visitablePos()) > 4
|| (town->garrisonHero && shortestPath.targetHero == town->garrisonHero.get()))
|| (town->getGarrisonHero() && shortestPath.targetHero == town->getGarrisonHero()))
return nullptr;
return shortestPath.targetHero;
@ -64,7 +64,7 @@ bool needToRecruitHero(const Nullkiller * ai, const CGTownInstance * startupTown
if(!ai->heroManager->canRecruitHero(startupTown))
return false;
if(!startupTown->garrisonHero && !startupTown->visitingHero)
if(!startupTown->getGarrisonHero() && !startupTown->getVisitingHero())
return true;
int treasureSourcesCount = 0;
@ -122,8 +122,8 @@ Goals::TGoalVec StartupBehavior::decompose(const Nullkiller * ai) const
{
startupTown = *vstd::maxElementByFun(towns, [ai](const CGTownInstance * town) -> float
{
if(town->garrisonHero)
return ai->heroManager->evaluateHero(town->garrisonHero.get());
if(town->getGarrisonHero())
return ai->heroManager->evaluateHero(town->getGarrisonHero());
auto closestHero = getNearestHero(ai, town);
@ -147,7 +147,7 @@ Goals::TGoalVec StartupBehavior::decompose(const Nullkiller * ai) const
if(closestHero)
{
if(!startupTown->visitingHero)
if(!startupTown->getVisitingHero())
{
if(ai->armyManager->howManyReinforcementsCanGet(startupTown->getUpperArmy(), startupTown->getUpperArmy(), closestHero, TerrainId::NONE) > 200)
{
@ -163,12 +163,12 @@ Goals::TGoalVec StartupBehavior::decompose(const Nullkiller * ai) const
}
else
{
auto visitingHero = startupTown->visitingHero.get();
auto visitingHero = startupTown->getVisitingHero();
auto visitingHeroScore = ai->heroManager->evaluateHero(visitingHero);
if(startupTown->garrisonHero)
if(startupTown->getGarrisonHero())
{
auto garrisonHero = startupTown->garrisonHero.get();
auto garrisonHero = startupTown->getGarrisonHero();
auto garrisonHeroScore = ai->heroManager->evaluateHero(garrisonHero);
if(visitingHeroScore > garrisonHeroScore
@ -187,7 +187,7 @@ Goals::TGoalVec StartupBehavior::decompose(const Nullkiller * ai) const
else if(canRecruitHero)
{
auto canPickTownArmy = startupTown->stacksCount() == 0
|| ai->armyManager->howManyReinforcementsCanGet(startupTown->visitingHero, startupTown) > 0;
|| ai->armyManager->howManyReinforcementsCanGet(startupTown->getVisitingHero(), startupTown) > 0;
if(canPickTownArmy)
{
@ -197,16 +197,16 @@ Goals::TGoalVec StartupBehavior::decompose(const Nullkiller * ai) const
}
}
if(tasks.empty() && canRecruitHero && !startupTown->visitingHero)
if(tasks.empty() && canRecruitHero && !startupTown->getVisitingHero())
{
tasks.push_back(Goals::sptr(Goals::RecruitHero(startupTown)));
}
if(tasks.empty() && !startupTown->visitingHero)
if(tasks.empty() && !startupTown->getVisitingHero())
{
for(auto town : towns)
{
if(!town->visitingHero && needToRecruitHero(ai, town))
if(!town->getVisitingHero() && needToRecruitHero(ai, town))
{
tasks.push_back(Goals::sptr(Goals::RecruitHero(town)));
@ -219,10 +219,10 @@ Goals::TGoalVec StartupBehavior::decompose(const Nullkiller * ai) const
{
for(const CGTownInstance * town : towns)
{
if(town->garrisonHero
&& town->garrisonHero->movementPointsRemaining()
&& !town->visitingHero
&& ai->getHeroLockedReason(town->garrisonHero) != HeroLockedReason::DEFENCE)
if(town->getGarrisonHero()
&& town->getGarrisonHero()->movementPointsRemaining()
&& !town->getVisitingHero()
&& ai->getHeroLockedReason(town->getGarrisonHero()) != HeroLockedReason::DEFENCE)
{
tasks.push_back(Goals::sptr(ExchangeSwapTownHeroes(town, nullptr).setpriority(MIN_PRIORITY)));
}

View File

@ -43,7 +43,7 @@ Goals::TGoalVec StayAtTownBehavior::decompose(const Nullkiller * ai) const
for(auto & path : paths)
{
if(town->visitingHero && town->visitingHero.get() != path.targetHero)
if(town->getVisitingHero() && town->getVisitingHero() != path.targetHero)
continue;
if(!path.getFirstBlockedAction() && path.exchangeCount <= 1)

View File

@ -47,16 +47,16 @@ ui64 FuzzyHelper::evaluateDanger(const int3 & tile, const CGHeroInstance * visit
{
auto hero = dynamic_cast<const CGHeroInstance *>(dangerousObject);
if(hero->visitedTown && !hero->visitedTown->garrisonHero)
if(hero->getVisitedTown() && !hero->getVisitedTown()->getGarrisonHero())
{
objectDanger += evaluateDanger(hero->visitedTown.get());
objectDanger += evaluateDanger(hero->getVisitedTown());
}
objectDanger *= ai->heroManager->getFightingStrengthCached(hero);
}
if (objWithID<Obj::TOWN>(dangerousObject))
{
auto town = dynamic_cast<const CGTownInstance*>(dangerousObject);
auto hero = town->garrisonHero;
auto hero = town->getGarrisonHero();
if (hero)
objectDanger *= ai->heroManager->getFightingStrengthCached(hero);
@ -121,7 +121,7 @@ ui64 FuzzyHelper::evaluateDanger(const CGObjectInstance * obj)
const CGTownInstance * town = dynamic_cast<const CGTownInstance *>(obj);
auto danger = town->getUpperArmy()->getArmyStrength();
if(danger || town->visitingHero)
if(danger || town->getVisitingHero())
{
auto fortLevel = town->fortLevel();

View File

@ -44,17 +44,17 @@ void AdventureSpellCast::accept(AIGateway * ai)
{
ai->selectedObject = town->id;
if(town->visitingHero && town->tempOwner == ai->playerID && !town->getUpperArmy()->stacksCount())
if(town->getVisitingHero() && town->tempOwner == ai->playerID && !town->getUpperArmy()->stacksCount())
{
ai->myCb->swapGarrisonHero(town);
}
if(town->visitingHero)
throw cannotFulfillGoalException("The town is already occupied by " + town->visitingHero->getNameTranslated());
if(town->getVisitingHero())
throw cannotFulfillGoalException("The town is already occupied by " + town->getVisitingHero()->getNameTranslated());
}
if (hero->inTownGarrison)
ai->myCb->swapGarrisonHero(hero->visitedTown);
if (hero->isGarrisoned())
ai->myCb->swapGarrisonHero(hero->getVisitedTown());
auto wait = cb->waitTillRealize;

View File

@ -97,9 +97,9 @@ void BuyArmy::accept(AIGateway * ai)
throw cannotFulfillGoalException("No creatures to buy.");
}
if(town->visitingHero && !town->garrisonHero)
if(town->getVisitingHero() && !town->getGarrisonHero())
{
ai->moveHeroToTile(town->visitablePos(), town->visitingHero.get());
ai->moveHeroToTile(town->visitablePos(), town->getVisitingHero());
}
}

View File

@ -19,7 +19,7 @@ namespace NKAI
using namespace Goals;
ExchangeSwapTownHeroes::ExchangeSwapTownHeroes(
const CGTownInstance * town,
const CGTownInstance * town,
const CGHeroInstance * garrisonHero,
HeroLockedReason lockingReason)
:ElementarGoal(Goals::EXCHANGE_SWAP_TOWN_HEROES), town(town), garrisonHero(garrisonHero), lockingReason(lockingReason)
@ -30,11 +30,11 @@ std::vector<ObjectInstanceID> ExchangeSwapTownHeroes::getAffectedObjects() const
{
std::vector<ObjectInstanceID> affectedObjects = { town->id };
if(town->garrisonHero)
affectedObjects.push_back(town->garrisonHero->id);
if(town->getGarrisonHero())
affectedObjects.push_back(town->getGarrisonHero()->id);
if(town->visitingHero)
affectedObjects.push_back(town->visitingHero->id);
if(town->getVisitingHero())
affectedObjects.push_back(town->getVisitingHero()->id);
return affectedObjects;
}
@ -42,8 +42,8 @@ std::vector<ObjectInstanceID> ExchangeSwapTownHeroes::getAffectedObjects() const
bool ExchangeSwapTownHeroes::isObjectAffected(ObjectInstanceID id) const
{
return town->id == id
|| (town->visitingHero && town->visitingHero->id == id)
|| (town->garrisonHero && town->garrisonHero->id == id);
|| (town->getVisitingHero() && town->getVisitingHero()->id == id)
|| (town->getGarrisonHero() && town->getGarrisonHero()->id == id);
}
std::string ExchangeSwapTownHeroes::toString() const
@ -58,39 +58,39 @@ bool ExchangeSwapTownHeroes::operator==(const ExchangeSwapTownHeroes & other) co
void ExchangeSwapTownHeroes::accept(AIGateway * ai)
{
if(!garrisonHero)
if(!getGarrisonHero())
{
auto currentGarrisonHero = town->garrisonHero;
auto currentGarrisonHero = town->getGarrisonHero();
if(!currentGarrisonHero)
throw cannotFulfillGoalException("Invalid configuration. There is no hero in town garrison.");
cb->swapGarrisonHero(town);
if(currentGarrisonHero.get() != town->visitingHero.get())
if(currentGarrisonHero != town->getVisitingHero())
{
logAi->error("VisitingHero is empty, expected %s", currentGarrisonHero->getNameTranslated());
return;
}
ai->buildArmyIn(town);
ai->nullkiller->unlockHero(currentGarrisonHero.get());
ai->nullkiller->unlockHero(currentGarrisonHero);
logAi->debug("Extracted hero %s from garrison of %s", currentGarrisonHero->getNameTranslated(), town->getNameTranslated());
return;
}
if(town->visitingHero && town->visitingHero.get() != garrisonHero)
if(town->getVisitingHero() && town->getVisitingHero() != getGarrisonHero())
cb->swapGarrisonHero(town);
ai->makePossibleUpgrades(town);
ai->moveHeroToTile(town->visitablePos(), garrisonHero);
ai->moveHeroToTile(town->visitablePos(), getGarrisonHero());
auto upperArmy = town->getUpperArmy();
if(!town->garrisonHero)
if(!town->getGarrisonHero())
{
if (!garrisonHero->canBeMergedWith(*town))
if (!getGarrisonHero()->canBeMergedWith(*town))
{
while (upperArmy->stacksCount() != 0)
{
@ -103,16 +103,16 @@ void ExchangeSwapTownHeroes::accept(AIGateway * ai)
if(lockingReason != HeroLockedReason::NOT_LOCKED)
{
ai->nullkiller->lockHero(garrisonHero, lockingReason);
ai->nullkiller->lockHero(getGarrisonHero(), lockingReason);
}
if(town->visitingHero && town->visitingHero != garrisonHero)
if(town->getVisitingHero() && town->getVisitingHero() != getGarrisonHero())
{
ai->nullkiller->unlockHero(town->visitingHero.get());
ai->makePossibleUpgrades(town->visitingHero);
ai->nullkiller->unlockHero(town->getVisitingHero());
ai->makePossibleUpgrades(town->getVisitingHero());
}
logAi->debug("Put hero %s to garrison of %s", garrisonHero->getNameTranslated(), town->getNameTranslated());
logAi->debug("Put hero %s to garrison of %s", getGarrisonHero()->getNameTranslated(), town->getNameTranslated());
}
}

View File

@ -59,12 +59,12 @@ void RecruitHero::accept(AIGateway * ai)
if(!heroToHire)
throw cannotFulfillGoalException("No hero to hire!");
if(t->visitingHero)
if(t->getVisitingHero())
{
cb->swapGarrisonHero(t);
}
if(t->visitingHero)
if(t->getVisitingHero())
throw cannotFulfillGoalException("Town " + t->nodeName() + " is occupied. Cannot recruit hero!");
cb->recruitHero(t, heroToHire);

View File

@ -958,7 +958,7 @@ void AINodeStorage::setHeroes(std::map<const CGHeroInstance *, HeroRole> heroes)
{
// do not allow our own heroes in garrison to act on map
if(hero.first->getOwner() == ai->playerID
&& hero.first->inTownGarrison
&& hero.first->isGarrisoned()
&& (ai->isHeroLocked(hero.first) || ai->heroManager->heroCapReached(false)))
{
continue;
@ -987,9 +987,9 @@ void AINodeStorage::setTownsAndDwellings(
{
uint64_t mask = FirstActorMask << actors.size();
// TODO: investigate logix of second condition || ai->nullkiller->getHeroLockedReason(town->garrisonHero) != HeroLockedReason::DEFENCE
// TODO: investigate logix of second condition || ai->nullkiller->getHeroLockedReason(town->getGarrisonHero()) != HeroLockedReason::DEFENCE
// check defence imrove
if(!town->garrisonHero)
if(!town->getGarrisonHero())
{
actors.push_back(std::make_shared<TownGarrisonActor>(town, mask));
}
@ -1185,19 +1185,19 @@ void AINodeStorage::calculateTownPortal(
{
for(const CGTownInstance * targetTown : towns)
{
if(targetTown->visitingHero
if(targetTown->getVisitingHero()
&& targetTown->getUpperArmy()->stacksCount()
&& maskMap.find(targetTown->visitingHero.get()) != maskMap.end())
&& maskMap.find(targetTown->getVisitingHero()) != maskMap.end())
{
auto basicMask = maskMap.at(targetTown->visitingHero.get());
auto basicMask = maskMap.at(targetTown->getVisitingHero());
bool sameActorInTown = actor->chainMask == basicMask;
if(!sameActorInTown)
continue;
}
if (targetTown->visitingHero
&& (targetTown->visitingHero.get()->getFactionID() != actor->hero->getFactionID()
if (targetTown->getVisitingHero()
&& (targetTown->getVisitingHero()->getFactionID() != actor->hero->getFactionID()
|| targetTown->getUpperArmy()->stacksCount()))
continue;

View File

@ -20,13 +20,13 @@ namespace AIPathfinding
{
void BuyArmyAction::execute(AIGateway * ai, const CGHeroInstance * hero) const
{
if(!hero->visitedTown)
if(!hero->getVisitedTown())
{
throw cannotFulfillGoalException(
hero->getNameTranslated() + " being at " + hero->visitablePos().toString() + " has no town to recruit creatures.");
}
ai->recruitCreatures(hero->visitedTown, hero);
ai->recruitCreatures(hero->getVisitedTown(), hero);
}
std::string BuyArmyAction::toString() const

View File

@ -39,8 +39,8 @@ TSubgoal AdventureSpellCast::whatToDoToAchieve()
if(hero->mana < hero->getSpellCost(spell))
throw cannotFulfillGoalException("Hero has not enough mana to cast " + spell->getNameTranslated());
if(spellID == SpellID::TOWN_PORTAL && town && town->visitingHero)
throw cannotFulfillGoalException("The town is already occupied by " + town->visitingHero->getNameTranslated());
if(spellID == SpellID::TOWN_PORTAL && town && town->getVisitingHero())
throw cannotFulfillGoalException("The town is already occupied by " + town->getVisitingHero()->getNameTranslated());
return iAmElementar();
}

View File

@ -32,7 +32,7 @@ TSubgoal BuildThis::whatToDoToAchieve()
// find town if not set
if(!town && hero)
town = hero->visitedTown;
town = hero->getVisitedTown();
if(!town)
{

View File

@ -56,14 +56,14 @@ TGoalVec GatherArmy::getAllPossibleSubgoals()
if(waysToVisit.size())
{
//grab army from town
if(!t->visitingHero && ai->ah->howManyReinforcementsCanGet(hero.get(), t))
if(!t->getVisitingHero() && ai->ah->howManyReinforcementsCanGet(hero.get(), t))
{
if(!vstd::contains(ai->townVisitsThisWeek[hero], t))
vstd::concatenate(ret, waysToVisit);
}
//buy army in town
if (!t->visitingHero || t->visitingHero == hero.get(true))
if (!t->getVisitingHero() || t->getVisitingHero() == hero.get(true))
{
std::vector<int> values = {
value,

View File

@ -75,9 +75,9 @@ TGoalVec GatherTroops::getAllPossibleSubgoals()
if(count >= this->value)
{
if(t->visitingHero)
if(t->getVisitingHero())
{
solutions.push_back(sptr(VisitObj(t->id.getNum()).sethero(t->visitingHero.get())));
solutions.push_back(sptr(VisitObj(t->id.getNum()).sethero(t->getVisitingHero())));
}
else
{

View File

@ -83,9 +83,9 @@ TSubgoal Win::whatToDoToAchieve()
if(auto h = ai->getHeroWithGrail())
{
//hero is in a town that can host Grail
if(h->visitedTown && !vstd::contains(h->visitedTown->forbiddenBuildings, BuildingID::GRAIL))
if(h->getVisitedTown() && !vstd::contains(h->getVisitedTown()->forbiddenBuildings, BuildingID::GRAIL))
{
const CGTownInstance * t = h->visitedTown;
const CGTownInstance * t = h->getVisitedTown();
return sptr(BuildThis(BuildingID::GRAIL, t).setpriority(10));
}
else

View File

@ -267,7 +267,7 @@ void AINodeStorage::calculateTownPortalTeleportations(
for(const CGTownInstance * targetTown : towns)
{
if(targetTown->visitingHero)
if(targetTown->getVisitingHero())
continue;
auto nodeOptional = getOrCreateNode(targetTown->visitablePos(), EPathfindingLayer::LAND, srcNode->chainMask | CAST_CHAIN);

View File

@ -486,8 +486,8 @@ void VCAI::playerBonusChanged(const Bonus & bonus, bool gain)
void VCAI::heroCreated(const CGHeroInstance * h)
{
LOG_TRACE(logAi);
if(h->visitedTown)
townVisitsThisWeek[HeroPtr(h)].insert(h->visitedTown);
if(h->getVisitedTown())
townVisitsThisWeek[HeroPtr(h)].insert(h->getVisitedTown());
NET_EVENT_HANDLER;
}
@ -1073,12 +1073,12 @@ void VCAI::performObjectInteraction(const CGObjectInstance * obj, HeroPtr h)
{
case Obj::TOWN:
moveCreaturesToHero(dynamic_cast<const CGTownInstance *>(obj));
if(h->visitedTown) //we are inside, not just attacking
if(h->getVisitedTown()) //we are inside, not just attacking
{
townVisitsThisWeek[h].insert(h->visitedTown);
townVisitsThisWeek[h].insert(h->getVisitedTown());
if(!h->hasSpellbook() && ah->freeGold() >= GameConstants::SPELLBOOK_GOLD_COST)
{
if(h->visitedTown->hasBuilt(BuildingID::MAGES_GUILD_1))
if(h->getVisitedTown()->hasBuilt(BuildingID::MAGES_GUILD_1))
cb->buyArtifact(h.get(), ArtifactID::SPELLBOOK);
}
}
@ -1089,9 +1089,9 @@ void VCAI::performObjectInteraction(const CGObjectInstance * obj, HeroPtr h)
void VCAI::moveCreaturesToHero(const CGTownInstance * t)
{
if(t->visitingHero && t->armedGarrison() && t->visitingHero->tempOwner == t->tempOwner)
if(t->getVisitingHero() && t->armedGarrison() && t->getVisitingHero()->tempOwner == t->tempOwner)
{
pickBestCreatures(t->visitingHero, t);
pickBestCreatures(t->getVisitingHero(), t);
}
}
@ -1363,10 +1363,10 @@ void VCAI::wander(HeroPtr h)
{
auto visitTownIfAny = [this](HeroPtr h) -> bool
{
if (h->visitedTown)
if (h->getVisitedTown())
{
townVisitsThisWeek[h].insert(h->visitedTown);
buildArmyIn(h->visitedTown);
townVisitsThisWeek[h].insert(h->getVisitedTown());
buildArmyIn(h->getVisitedTown());
return true;
}
return false;
@ -1434,7 +1434,7 @@ void VCAI::wander(HeroPtr h)
std::vector<const CGTownInstance *> townsNotReachable;
for(const CGTownInstance * t : cb->getTownsInfo())
{
if(!t->visitingHero && !vstd::contains(townVisitsThisWeek[h], t))
if(!t->getVisitingHero() && !vstd::contains(townVisitsThisWeek[h], t))
{
if(isAccessibleForHero(t->visitablePos(), h))
townsReachable.push_back(t);
@ -2251,7 +2251,7 @@ void VCAI::tryRealize(Goals::AbstractGoal & g)
const CGTownInstance * VCAI::findTownWithTavern() const
{
for(const CGTownInstance * t : cb->getTownsInfo())
if(t->hasBuilt(BuildingID::TAVERN) && !t->visitingHero)
if(t->hasBuilt(BuildingID::TAVERN) && !t->getVisitingHero())
return t;
return nullptr;
@ -2455,7 +2455,7 @@ void VCAI::performTypicalActions()
void VCAI::buildArmyIn(const CGTownInstance * t)
{
makePossibleUpgrades(t->visitingHero);
makePossibleUpgrades(t->getVisitingHero());
makePossibleUpgrades(t);
recruitCreatures(t, t->getUpperArmy());
moveCreaturesToHero(t);

View File

@ -273,7 +273,7 @@ void CCallback::spellResearch( const CGTownInstance *town, SpellID spellAtSlot,
void CCallback::swapGarrisonHero( const CGTownInstance *town )
{
if(town->tempOwner == *player || (town->garrisonHero && town->garrisonHero->tempOwner == *player ))
if(town->tempOwner == *player || (town->getGarrisonHero() && town->getGarrisonHero()->tempOwner == *player ))
{
GarrisonHeroSwap pack(town->id);
sendRequest(pack);

View File

@ -118,18 +118,6 @@
std::shared_ptr<BattleInterface> CPlayerInterface::battleInt;
struct HeroObjectRetriever
{
const CGHeroInstance * operator()(const ConstTransitivePtr<CGHeroInstance> &h) const
{
return h;
}
const CGHeroInstance * operator()(const ConstTransitivePtr<CStackInstance> &s) const
{
return nullptr;
}
};
CPlayerInterface::CPlayerInterface(PlayerColor Player):
localState(std::make_unique<PlayerLocalState>(*this)),
movementController(std::make_unique<HeroMovementController>()),
@ -542,18 +530,18 @@ void CPlayerInterface::heroInGarrisonChange(const CGTownInstance *town)
{
EVENT_HANDLER_CALLED_BY_CLIENT;
if(town->garrisonHero) //wandering hero moved to the garrison
if(town->getGarrisonHero()) //wandering hero moved to the garrison
{
// This method also gets called on hero recruitment -> garrisoned hero is already in garrison
if(town->garrisonHero->tempOwner == playerID && vstd::contains(localState->getWanderingHeroes(), town->garrisonHero))
localState->removeWanderingHero(town->garrisonHero);
if(town->getGarrisonHero()->tempOwner == playerID && vstd::contains(localState->getWanderingHeroes(), town->getGarrisonHero()))
localState->removeWanderingHero(town->getGarrisonHero());
}
if(town->visitingHero) //hero leaves garrison
if(town->getVisitingHero()) //hero leaves garrison
{
// This method also gets called on hero recruitment -> wandering heroes already contains new hero
if(town->visitingHero->tempOwner == playerID && !vstd::contains(localState->getWanderingHeroes(), town->visitingHero))
localState->addWanderingHero(town->visitingHero);
if(town->getVisitingHero()->tempOwner == playerID && !vstd::contains(localState->getWanderingHeroes(), town->getVisitingHero()))
localState->addWanderingHero(town->getVisitingHero());
}
adventureInt->onHeroChanged(nullptr);
adventureInt->onTownChanged(town);
@ -611,8 +599,8 @@ void CPlayerInterface::garrisonsChanged(std::vector<const CArmedInstance *> objs
localState->verifyPath(hero);
adventureInt->onHeroChanged(hero);
if(hero->inTownGarrison && hero->visitedTown != town)
adventureInt->onTownChanged(hero->visitedTown);
if(hero->isGarrisoned() && hero->getVisitedTown() != town)
adventureInt->onTownChanged(hero->getVisitedTown());
}
}
@ -1363,7 +1351,7 @@ void CPlayerInterface::initializeHeroTownList()
{
for(auto & hero : cb->getHeroesInfo())
{
if(!hero->inTownGarrison)
if(!hero->isGarrisoned())
localState->addWanderingHero(hero);
}
}

View File

@ -703,7 +703,7 @@ void ApplyClientNetPackVisitor::visitCommanderLevelUp(CommanderLevelUp & pack)
{
const CGHeroInstance * hero = cl.getHero(pack.heroId);
assert(hero);
const CCommanderInstance * commander = hero->commander;
const auto & commander = hero->getCommander();
assert(commander);
assert(commander->armyObj); //is it possible for Commander to exist beyond armed instance?
callOnlyThatInterface(cl, pack.player, &CGameInterface::commanderGotLevel, commander, pack.skills, pack.queryID);

View File

@ -132,7 +132,7 @@ double MapRendererBaseContext::objectTransparency(ObjectInstanceID objectID, con
{
const auto * hero = dynamic_cast<const CGHeroInstance *>(object);
if(hero->inTownGarrison)
if(hero->isGarrisoned())
return 0;
if(hero->boat)

View File

@ -81,7 +81,7 @@ void CGarrisonSlot::hover (bool on)
const bool isHeroOnMap = owner->upperArmy() // Hero is not a visitor and not a garrison defender
&& owner->upperArmy()->ID == Obj::HERO
&& (!owner->lowerArmy() || owner->lowerArmy()->ID == Obj::HERO) // one hero or we are in the Heroes exchange window
&& !(static_cast<const CGHeroInstance*>(owner->upperArmy()))->inTownGarrison;
&& !(static_cast<const CGHeroInstance*>(owner->upperArmy()))->isGarrisoned();
if(isHeroOnMap)
{

View File

@ -595,16 +595,16 @@ HeroSlots::HeroSlots(const CGTownInstance * Town, Point garrPos, Point visitPos,
garr(Garrison)
{
OBJECT_CONSTRUCTION;
garrisonedHero = std::make_shared<CHeroGSlot>(garrPos.x, garrPos.y, 0, town->garrisonHero, this);
visitingHero = std::make_shared<CHeroGSlot>(visitPos.x, visitPos.y, 1, town->visitingHero, this);
garrisonedHero = std::make_shared<CHeroGSlot>(garrPos.x, garrPos.y, 0, town->getGarrisonHero(), this);
visitingHero = std::make_shared<CHeroGSlot>(visitPos.x, visitPos.y, 1, town->getVisitingHero(), this);
}
HeroSlots::~HeroSlots() = default;
void HeroSlots::update()
{
garrisonedHero->set(town->garrisonHero);
visitingHero->set(town->visitingHero);
garrisonedHero->set(town->getGarrisonHero());
visitingHero->set(town->getVisitingHero());
}
void HeroSlots::swapArmies()
@ -612,9 +612,9 @@ void HeroSlots::swapArmies()
bool allow = true;
//moving hero out of town - check if it is allowed
if (town->garrisonHero)
if (town->getGarrisonHero())
{
if (!town->visitingHero && GAME->interface()->cb->howManyHeroes(false) >= GAME->interface()->cb->getSettings().getInteger(EGameSettings::HEROES_PER_PLAYER_ON_MAP_CAP))
if (!town->getVisitingHero() && GAME->interface()->cb->howManyHeroes(false) >= GAME->interface()->cb->getSettings().getInteger(EGameSettings::HEROES_PER_PLAYER_ON_MAP_CAP))
{
std::string text = LIBRARY->generaltexth->translate("core.genrltxt.18"); //You already have %d adventuring heroes under your command.
boost::algorithm::replace_first(text,"%d",std::to_string(GAME->interface()->cb->howManyHeroes(false)));
@ -622,7 +622,7 @@ void HeroSlots::swapArmies()
GAME->interface()->showInfoDialog(text, std::vector<std::shared_ptr<CComponent>>(), soundBase::sound_todo);
allow = false;
}
else if (town->garrisonHero->stacksCount() == 0)
else if (town->getGarrisonHero()->stacksCount() == 0)
{
//This hero has no creatures. A hero must have creatures before he can brave the dangers of the countryside.
GAME->interface()->showInfoDialog(LIBRARY->generaltexth->translate("core.genrltxt.19"), {}, soundBase::sound_todo);
@ -630,9 +630,9 @@ void HeroSlots::swapArmies()
}
}
if(!town->garrisonHero && town->visitingHero) //visiting => garrison, merge armies: town army => hero army
if(!town->getGarrisonHero() && town->getVisitingHero()) //visiting => garrison, merge armies: town army => hero army
{
if(!town->visitingHero->canBeMergedWith(*town))
if(!town->getVisitingHero()->canBeMergedWith(*town))
{
GAME->interface()->showInfoDialog(LIBRARY->generaltexth->allTexts[275], std::vector<std::shared_ptr<CComponent>>(), soundBase::sound_todo);
allow = false;
@ -809,10 +809,10 @@ void CCastleBuildings::removeBuilding(BuildingID building)
const CGHeroInstance * CCastleBuildings::getHero()
{
if(town->visitingHero)
return town->visitingHero;
if(town->getVisitingHero())
return town->getVisitingHero();
else
return town->garrisonHero;
return town->getGarrisonHero();
}
void CCastleBuildings::buildingClicked(BuildingID building)
@ -983,7 +983,7 @@ bool CCastleBuildings::buildingTryActivateCustomUI(BuildingID buildingToTest, Bu
void CCastleBuildings::enterRewardable(BuildingID building)
{
if (town->visitingHero == nullptr)
if (town->getVisitingHero() == nullptr)
{
MetaString message;
message.appendTextID("core.genrltxt.273"); // only visiting heroes may visit %s
@ -993,7 +993,7 @@ void CCastleBuildings::enterRewardable(BuildingID building)
}
else
{
if (town->rewardableBuildings.at(building)->wasVisited(town->visitingHero))
if (town->rewardableBuildings.at(building)->wasVisited(town->getVisitingHero()))
enterBuilding(building);
else
GAME->interface()->cb->visitTownBuilding(town, building);
@ -1002,7 +1002,7 @@ void CCastleBuildings::enterRewardable(BuildingID building)
void CCastleBuildings::enterBlacksmith(BuildingID building, ArtifactID artifactID)
{
const CGHeroInstance *hero = town->visitingHero;
const CGHeroInstance *hero = town->getVisitingHero();
if(!hero)
{
GAME->interface()->showInfoDialog(boost::str(boost::format(LIBRARY->generaltexth->allTexts[273]) % town->getTown()->buildings.find(building)->second->getNameTranslated()));
@ -1040,7 +1040,7 @@ void CCastleBuildings::enterBuilding(BuildingID building)
void CCastleBuildings::enterCastleGate(BuildingID building)
{
if (!town->visitingHero)
if (!town->getVisitingHero())
{
GAME->interface()->showInfoDialog(LIBRARY->generaltexth->allTexts[126]);
return;//only visiting hero can use castle gates
@ -1051,7 +1051,7 @@ void CCastleBuildings::enterCastleGate(BuildingID building)
for(auto & Town : Towns)
{
const CGTownInstance *t = Town;
if (t->id != this->town->id && t->visitingHero == nullptr && //another town, empty and this is
if (t->id != this->town->id && t->getVisitingHero() == nullptr && //another town, empty and this is
t->getFactionID() == town->getFactionID() && //the town of the same faction
t->hasBuilt(BuildingSubID::CASTLE_GATE)) //and the town has a castle gate
{
@ -1169,7 +1169,7 @@ void CCastleBuildings::enterMagesGuild()
void CCastleBuildings::enterTownHall()
{
if(town->visitingHero && town->visitingHero->hasArt(ArtifactID::GRAIL) &&
if(town->getVisitingHero() && town->getVisitingHero()->hasArt(ArtifactID::GRAIL) &&
!town->hasBuilt(BuildingID::GRAIL)) //hero has grail, but town does not have it
{
if(!vstd::contains(town->forbiddenBuildings, BuildingID::GRAIL))
@ -1427,7 +1427,7 @@ CCastleInterface::CCastleInterface(const CGTownInstance * Town, const CGTownInst
center();
updateShadow();
garr = std::make_shared<CGarrisonInt>(Point(305, 387), 4, Point(0,96), town->getUpperArmy(), town->visitingHero);
garr = std::make_shared<CGarrisonInt>(Point(305, 387), 4, Point(0,96), town->getUpperArmy(), town->getVisitingHero());
garr->setRedrawParent(true);
heroes = std::make_shared<HeroSlots>(town, Point(241, 387), Point(241, 483), garr, true);
@ -1476,7 +1476,7 @@ CCastleInterface::~CCastleInterface()
void CCastleInterface::updateGarrisons()
{
garr->setArmy(town->getUpperArmy(), EGarrisonType::UPPER);
garr->setArmy(town->visitingHero, EGarrisonType::LOWER);
garr->setArmy(town->getVisitingHero(), EGarrisonType::LOWER);
garr->recreateSlots();
heroes->update();
@ -1485,15 +1485,15 @@ void CCastleInterface::updateGarrisons()
bool CCastleInterface::holdsGarrison(const CArmedInstance * army)
{
return army == town || army == town->getUpperArmy() || army == town->visitingHero;
return army == town || army == town->getUpperArmy() || army == town->getVisitingHero();
}
void CCastleInterface::close()
{
if(town->tempOwner == GAME->interface()->playerID) //we may have opened window for an allied town
{
if(town->visitingHero && town->visitingHero->tempOwner == GAME->interface()->playerID)
GAME->interface()->localState->setSelection(town->visitingHero);
if(town->getVisitingHero() && town->getVisitingHero()->tempOwner == GAME->interface()->playerID)
GAME->interface()->localState->setSelection(town->getVisitingHero());
else
GAME->interface()->localState->setSelection(town);
}
@ -1503,9 +1503,9 @@ void CCastleInterface::close()
void CCastleInterface::castleTeleport(int where)
{
const CGTownInstance * dest = GAME->interface()->cb->getTown(ObjectInstanceID(where));
GAME->interface()->localState->setSelection(town->visitingHero);//according to assert(ho == adventureInt->selection) in the eraseCurrentPathOf
GAME->interface()->cb->teleportHero(town->visitingHero, dest);
GAME->interface()->localState->erasePath(town->visitingHero);
GAME->interface()->localState->setSelection(town->getVisitingHero());//according to assert(ho == adventureInt->selection) in the eraseCurrentPathOf
GAME->interface()->cb->teleportHero(town->getVisitingHero(), dest);
GAME->interface()->localState->erasePath(town->getVisitingHero());
}
void CCastleInterface::townChange()
@ -1605,22 +1605,22 @@ void CCastleInterface::keyPressed(EShortcut key)
case EShortcut::TOWN_OPEN_THIEVES_GUILD:
break;
case EShortcut::TOWN_OPEN_HERO_EXCHANGE:
if (town->visitingHero && town->garrisonHero)
GAME->interface()->showHeroExchange(town->visitingHero->id, town->garrisonHero->id);
if (town->getVisitingHero() && town->getGarrisonHero())
GAME->interface()->showHeroExchange(town->getVisitingHero()->id, town->getGarrisonHero()->id);
break;
case EShortcut::TOWN_OPEN_HERO:
if (town->visitingHero)
GAME->interface()->openHeroWindow(town->visitingHero);
else if (town->garrisonHero)
GAME->interface()->openHeroWindow(town->garrisonHero);
if (town->getVisitingHero())
GAME->interface()->openHeroWindow(town->getVisitingHero());
else if (town->getGarrisonHero())
GAME->interface()->openHeroWindow(town->getGarrisonHero());
break;
case EShortcut::TOWN_OPEN_VISITING_HERO:
if (town->visitingHero)
GAME->interface()->openHeroWindow(town->visitingHero);
if (town->getVisitingHero())
GAME->interface()->openHeroWindow(town->getVisitingHero());
break;
case EShortcut::TOWN_OPEN_GARRISONED_HERO:
if (town->garrisonHero)
GAME->interface()->openHeroWindow(town->garrisonHero);
if (town->getGarrisonHero())
GAME->interface()->openHeroWindow(town->getGarrisonHero());
break;
case EShortcut::TOWN_SWAP_ARMIES:
heroes->swapArmies();

View File

@ -104,7 +104,7 @@ CHeroWindow::CHeroWindow(const CGHeroInstance * hero)
formations->addToggle(0, std::make_shared<CToggleButton>(Point(481, 483), AnimationPath::builtin("hsbtns6.def"), std::make_pair(heroscrn[23], heroscrn[29]), 0, EShortcut::HERO_TIGHT_FORMATION));
formations->addToggle(1, std::make_shared<CToggleButton>(Point(481, 519), AnimationPath::builtin("hsbtns7.def"), std::make_pair(heroscrn[24], heroscrn[30]), 0, EShortcut::HERO_LOOSE_FORMATION));
if(hero->commander)
if(hero->getCommander())
{
commanderButton = std::make_shared<CButton>(Point(317, 18), AnimationPath::builtin("heroCommander"), CButton::tooltipLocalized("vcmi.heroWindow.openCommander"), [&](){ commanderWindow(); }, EShortcut::HERO_COMMANDER);
commanderButton->setOverlay(std::make_shared<CPicture>(ImagePath::builtin("heroWindow/commanderButtonIcon")));
@ -328,7 +328,7 @@ void CHeroWindow::commanderWindow()
if(pickedArtInst)
{
const auto freeSlot = ArtifactUtils::getArtAnyPosition(curHero->commander, pickedArtInst->getTypeId());
const auto freeSlot = ArtifactUtils::getArtAnyPosition(curHero->getCommander(), pickedArtInst->getTypeId());
if(vstd::contains(ArtifactUtils::commanderSlots(), freeSlot)) // We don't want to put it in commander's backpack!
{
ArtifactLocation dst(curHero->id, freeSlot);
@ -338,7 +338,7 @@ void CHeroWindow::commanderWindow()
}
else
{
ENGINE->windows().createAndPushWindow<CStackWindow>(curHero->commander, false);
ENGINE->windows().createAndPushWindow<CStackWindow>(curHero->getCommander(), false);
}
}

View File

@ -785,7 +785,7 @@ CTownItem::CTownItem(const CGTownInstance * Town)
hall = std::make_shared<CTownInfo>( 69, 31, town, true);
fort = std::make_shared<CTownInfo>(111, 31, town, false);
garr = std::make_shared<CGarrisonInt>(Point(313, 3), 4, Point(232,0), town->getUpperArmy(), town->visitingHero, true, true, CGarrisonInt::ESlotsLayout::TWO_ROWS);
garr = std::make_shared<CGarrisonInt>(Point(313, 3), 4, Point(232,0), town->getUpperArmy(), town->getVisitingHero(), true, true, CGarrisonInt::ESlotsLayout::TWO_ROWS);
heroes = std::make_shared<HeroSlots>(town, Point(244,6), Point(475,6), garr, false);
size_t iconIndex = town->getTown()->clientInfo.icons[town->hasFort()][town->built >= GAME->interface()->cb->getSettings().getInteger(EGameSettings::TOWNS_BUILDINGS_PER_TURN_CAP)];
@ -837,13 +837,13 @@ void CTownItem::updateGarrisons()
{
garr->selectSlot(nullptr);
garr->setArmy(town->getUpperArmy(), EGarrisonType::UPPER);
garr->setArmy(town->visitingHero, EGarrisonType::LOWER);
garr->setArmy(town->getVisitingHero(), EGarrisonType::LOWER);
garr->recreateSlots();
}
bool CTownItem::holdsGarrison(const CArmedInstance * army)
{
return army == town || army == town->getUpperArmy() || army == town->visitingHero;
return army == town || army == town->getUpperArmy() || army == town->getVisitingHero();
}
void CTownItem::update()

View File

@ -517,7 +517,7 @@ CTavernWindow::CTavernWindow(const CGObjectInstance * TavernObj, const std::func
recruit->addHoverText(EButtonState::NORMAL, message.toString());
recruit->block(true);
}
else if(dynamic_cast<const CGTownInstance *>(TavernObj) && dynamic_cast<const CGTownInstance *>(TavernObj)->visitingHero)
else if(dynamic_cast<const CGTownInstance *>(TavernObj) && dynamic_cast<const CGTownInstance *>(TavernObj)->getVisitingHero())
{
recruit->addHoverText(EButtonState::NORMAL, LIBRARY->generaltexth->tavernInfo[2]); //Cannot recruit. You already have a Hero in this town.
recruit->block(true);

View File

@ -499,7 +499,7 @@ bool CCreatureSet::contains(const CStackInstance *stack) const
SlotID CCreatureSet::findStack(const CStackInstance *stack) const
{
const auto * h = dynamic_cast<const CGHeroInstance *>(this);
if (h && h->commander == stack)
if (h && h->getCommander() == stack)
return SlotID::COMMANDER_SLOT_PLACEHOLDER;
if(!stack)

View File

@ -721,7 +721,7 @@ int CGameInfoCallback::getHeroCount( PlayerColor player, bool includeGarrisoned
return static_cast<int>(p->getHeroes().size());
else
for(const auto & elem : p->getHeroes())
if(!elem->inTownGarrison)
if(!elem->isGarrisoned())
ret++;
return ret;
}
@ -792,7 +792,7 @@ std::vector < const CGHeroInstance *> CPlayerSpecificInfoCallback::getHeroesInfo
int CPlayerSpecificInfoCallback::getHeroSerial(const CGHeroInstance * hero, bool includeGarrisoned) const
{
if (hero->inTownGarrison && !includeGarrisoned)
if (hero->isGarrisoned() && !includeGarrisoned)
return -1;
size_t index = 0;
@ -800,7 +800,7 @@ int CPlayerSpecificInfoCallback::getHeroSerial(const CGHeroInstance * hero, bool
for (auto & possibleHero : heroes)
{
if (includeGarrisoned || !(possibleHero)->inTownGarrison)
if (includeGarrisoned || !(possibleHero)->isGarrisoned())
index++;
if (possibleHero == hero)
@ -853,7 +853,7 @@ const CGHeroInstance* CPlayerSpecificInfoCallback::getHeroBySerial(int serialId,
if (!includeGarrisoned)
{
for(ui32 i = 0; i < p->getHeroes().size() && static_cast<int>(i) <= serialId; i++)
if(p->getHeroes()[i]->inTownGarrison)
if(p->getHeroes()[i]->isGarrisoned())
serialId++;
}
ERROR_RET_VAL_IF(serialId < 0 || serialId >= p->getHeroes().size(), "No player info", nullptr);

View File

@ -410,7 +410,7 @@ void CStack::postDeserialize(const CArmedInstance * army, const SlotID & extSlot
{
const auto * hero = dynamic_cast<const CGHeroInstance *>(army);
assert(hero);
base = hero->commander;
base = hero->getCommander();
}
else if(slot == SlotID::SUMMONED_SLOT_PLACEHOLDER || slot == SlotID::ARROW_TOWERS_SLOT || slot == SlotID::WAR_MACHINES_SLOT)
{

View File

@ -271,7 +271,7 @@ CArtifactSet * CNonConstInfoCallback::getArtSet(const ArtifactLocation & loc)
if(loc.creature.has_value())
{
if(loc.creature.value() == SlotID::COMMANDER_SLOT_PLACEHOLDER)
return hero->commander;
return hero->getCommander();
else
return hero->getStackPtr(loc.creature.value());
}

View File

@ -351,9 +351,9 @@ BattleInfo * BattleInfo::setupBattle(const int3 & tile, TerrainId terrain, const
//adding commanders
for(BattleSide i : {BattleSide::ATTACKER, BattleSide::DEFENDER})
{
if (heroes[i] && heroes[i]->commander && heroes[i]->commander->alive)
if (heroes[i] && heroes[i]->getCommander() && heroes[i]->getCommander()->alive)
{
currentBattle->generateNewStack(currentBattle->nextUnitId(), *heroes[i]->commander, i, SlotID::COMMANDER_SLOT_PLACEHOLDER, layout.commanders.at(i));
currentBattle->generateNewStack(currentBattle->nextUnitId(), *heroes[i]->getCommander(), i, SlotID::COMMANDER_SLOT_PLACEHOLDER, layout.commanders.at(i));
}
}

View File

@ -992,7 +992,7 @@ void CGameState::initVisitingAndGarrisonedHeroes()
if (t->visitableAt(h->visitablePos()))
{
assert(t->visitingHero == nullptr);
assert(t->getVisitingHero() == nullptr);
t->setVisitingHero(h);
}
}
@ -1000,9 +1000,9 @@ void CGameState::initVisitingAndGarrisonedHeroes()
}
for (auto hero : map->heroesOnMap)
{
if (hero->visitedTown)
if (hero->getVisitedTown())
{
assert (hero->visitedTown->visitingHero == hero);
assert (hero->getVisitedTown()->getVisitingHero() == hero);
}
}
}
@ -1092,9 +1092,9 @@ UpgradeInfo CGameState::fillUpgradeInfo(const CStackInstance & stack) const
auto hero = dynamic_cast<const CGHeroInstance *>(stack.armyObj);
hero->fillUpgradeInfo(ret, stack);
if (hero->visitedTown)
if (hero->getVisitedTown())
{
hero->visitedTown->fillUpgradeInfo(ret, stack);
hero->getVisitedTown()->fillUpgradeInfo(ret, stack);
}
else
{
@ -1382,8 +1382,8 @@ bool CGameState::checkForVictory(const PlayerColor & player, const EventConditio
case EventCondition::TRANSPORT:
{
const auto * t = getTown(condition.objectID);
bool garrisonedWon = t->garrisonHero && t->garrisonHero->getOwner() == player && t->garrisonHero->hasArt(condition.objectType.as<ArtifactID>());
bool visitingWon = t->visitingHero && t->visitingHero->getOwner() == player && t->visitingHero->hasArt(condition.objectType.as<ArtifactID>());
bool garrisonedWon = t->getGarrisonHero() && t->getGarrisonHero()->getOwner() == player && t->getGarrisonHero()->hasArt(condition.objectType.as<ArtifactID>());
bool visitingWon = t->getVisitingHero() && t->getVisitingHero()->getOwner() == player && t->getVisitingHero()->hasArt(condition.objectType.as<ArtifactID>());
return garrisonedWon || visitingWon;
}

View File

@ -244,7 +244,7 @@ si64 Statistic::getArmyStrength(const PlayerState * ps, bool withTownGarrison)
for(auto h : ps->getHeroes())
{
if(!h->inTownGarrison || withTownGarrison) //original h3 behavior
if(!h->isGarrisoned() || withTownGarrison) //original h3 behavior
str += h->getArmyStrength();
}
return str;

View File

@ -183,7 +183,7 @@ void InfoAboutTown::initFromTown(const CGTownInstance *t, bool detailed)
details->goldIncome = income[EGameResID::GOLD];
details->customRes = t->hasBuilt(BuildingID::RESOURCE_SILO);
details->hallLevel = t->hallLevel();
details->garrisonedHero = t->garrisonHero;
details->garrisonedHero = t->getGarrisonHero();
}
}

View File

@ -308,6 +308,47 @@ void CGHeroInstance::setHeroType(HeroTypeID heroType)
subID = heroType;
}
bool CGHeroInstance::isGarrisoned() const
{
return inTownGarrison;
}
const CGTownInstance * CGHeroInstance::getVisitedTown() const
{
if (!visitedTown.hasValue())
return nullptr;
return cb->getTown(visitedTown);
}
CGTownInstance * CGHeroInstance::getVisitedTown()
{
if (!visitedTown.hasValue())
return nullptr;
return dynamic_cast<CGTownInstance*>(cb->gameState()->getObjInstance(visitedTown));
}
void CGHeroInstance::setVisitedTown(const CGTownInstance * town, bool garrisoned)
{
if (town)
visitedTown = town->id;
else
visitedTown = {};
inTownGarrison = garrisoned;
}
const CCommanderInstance * CGHeroInstance::getCommander() const
{
return commander.get();
}
CCommanderInstance * CGHeroInstance::getCommander()
{
return commander.get();
}
void CGHeroInstance::initObj(vstd::RNG & rand)
{
if (ID == Obj::HERO)
@ -423,7 +464,7 @@ void CGHeroInstance::initHero(vstd::RNG & rand)
if (cb->getSettings().getBoolean(EGameSettings::MODULE_COMMANDERS) && !commander && getHeroClass()->commander.hasValue())
{
commander = new CCommanderInstance(getHeroClass()->commander);
commander = std::make_unique<CCommanderInstance>(getHeroClass()->commander);
commander->setArmyObj (castToArmyObj()); //TODO: separate function for setting commanders
commander->giveStackExp (exp); //after our exp is set
}
@ -504,10 +545,7 @@ void CGHeroInstance::initArmy(vstd::RNG & rand, IArmyDescriptor * dst)
}
}
CGHeroInstance::~CGHeroInstance()
{
commander.dellNull();
}
CGHeroInstance::~CGHeroInstance() = default;
bool CGHeroInstance::needsLastStack() const
{
@ -527,8 +565,8 @@ void CGHeroInstance::onHeroVisit(const CGHeroInstance * h) const
}
else //battle
{
if(visitedTown) //we're in town
visitedTown->onHeroVisit(h); //town will handle attacking
if(getVisitedTown()) //we're in town
getVisitedTown()->onHeroVisit(h); //town will handle attacking
else
cb->startBattle(h, this);
}
@ -1060,7 +1098,7 @@ si32 CGHeroInstance::manaRegain() const
si32 CGHeroInstance::getManaNewTurn() const
{
if(visitedTown && visitedTown->hasBuilt(BuildingID::MAGES_GUILD_1))
if(getVisitedTown() && getVisitedTown()->hasBuilt(BuildingID::MAGES_GUILD_1))
{
//if hero starts turn in town with mage guild - restore all mana
return std::max(mana, manaLimit());
@ -1280,30 +1318,30 @@ void CGHeroInstance::boatDeserializationFix()
CBonusSystemNode * CGHeroInstance::whereShouldBeAttachedOnSiege(const bool isBattleOutsideTown) const
{
if(!visitedTown)
if(!getVisitedTown())
return nullptr;
return isBattleOutsideTown ? (CBonusSystemNode *)(& visitedTown->townAndVis)
: (CBonusSystemNode *)(visitedTown.get());
return isBattleOutsideTown ? (CBonusSystemNode *)(& getVisitedTown()->townAndVis)
: (CBonusSystemNode *)(getVisitedTown());
}
CBonusSystemNode * CGHeroInstance::whereShouldBeAttachedOnSiege(CGameState * gs)
{
if(visitedTown)
return whereShouldBeAttachedOnSiege(visitedTown->isBattleOutsideTown(this));
if(getVisitedTown())
return whereShouldBeAttachedOnSiege(getVisitedTown()->isBattleOutsideTown(this));
return &CArmedInstance::whereShouldBeAttached(gs);
}
CBonusSystemNode & CGHeroInstance::whereShouldBeAttached(CGameState * gs)
{
if(visitedTown)
if(getVisitedTown())
{
if(inTownGarrison)
return *visitedTown;
if(isGarrisoned())
return *getVisitedTown();
else
return visitedTown->townAndVis;
return getVisitedTown()->townAndVis;
}
else
return CArmedInstance::whereShouldBeAttached(gs);

View File

@ -17,7 +17,6 @@
#include "../bonuses/BonusCache.h"
#include "../entities/hero/EHeroGender.h"
#include "../CArtHandler.h" // For CArtifactSet
#include "../ConstTransitivePtr.h"
VCMI_LIB_NAMESPACE_BEGIN
@ -66,12 +65,14 @@ private:
MagicSchoolMasteryCache magicSchoolMastery;
BonusValueCache manaPerKnowledgeCached;
std::unique_ptr<TurnInfoCache> turnInfoCache;
std::unique_ptr<CCommanderInstance> commander;
std::set<SpellID> spells; //known spells (spell IDs)
ObjectInstanceID visitedTown; //set if hero is visiting town or in the town garrison
ui32 movement; //remaining movement points
bool inTownGarrison; // if hero is in town garrison
public:
//////////////////////////////////////////////////////////////////////////
//format: 123
// 8 4
@ -93,9 +94,6 @@ public:
std::string nameCustomTextId;
std::string biographyCustomTextId;
bool inTownGarrison; // if hero is in town garrison
ConstTransitivePtr<CGTownInstance> visitedTown; //set if hero is visiting town or in the town garrison
ConstTransitivePtr<CCommanderInstance> commander;
const CGBoat * boat = nullptr; //set to CGBoat when sailing
static constexpr si32 UNINITIALIZED_MANA = -1;
@ -103,8 +101,6 @@ public:
static constexpr auto UNINITIALIZED_EXPERIENCE = std::numeric_limits<TExpType>::max();
static const ui32 NO_PATROLLING;
//std::vector<const CArtifact*> artifacts; //hero's artifacts from bag
//std::map<ui16, const CArtifact*> artifWorn; //map<position,artifact_id>; positions: 0 - head; 1 - shoulders; 2 - neck; 3 - right hand; 4 - left hand; 5 - torso; 6 - right ring; 7 - left ring; 8 - feet; 9 - misc1; 10 - misc2; 11 - misc3; 12 - misc4; 13 - mach1; 14 - mach2; 15 - mach3; 16 - mach4; 17 - spellbook; 18 - misc5
std::set<ObjectInstanceID> visitedObjects;
struct DLL_LINKAGE Patrol
@ -252,6 +248,14 @@ public:
HeroTypeID getHeroTypeID() const;
void setHeroType(HeroTypeID type);
bool isGarrisoned() const;
const CGTownInstance * getVisitedTown() const;
CGTownInstance * getVisitedTown();
void setVisitedTown(const CGTownInstance * town, bool garrisoned);
const CCommanderInstance * getCommander() const;
CCommanderInstance * getCommander();
void initObj(vstd::RNG & rand) override;
void initHero(vstd::RNG & rand);
void initHero(vstd::RNG & rand, const HeroTypeID & SUBID);

View File

@ -59,13 +59,13 @@ void CGTownInstance::setPropertyDer(ObjProperty what, ObjPropertyID identifier)
switch (what)
{
case ObjProperty::STRUCTURE_ADD_VISITING_HERO:
rewardableBuildings.at(identifier.getNum())->setProperty(ObjProperty::VISITORS, visitingHero->id);
rewardableBuildings.at(identifier.getNum())->setProperty(ObjProperty::VISITORS, getVisitingHero()->id);
break;
case ObjProperty::STRUCTURE_CLEAR_VISITORS:
rewardableBuildings.at(identifier.getNum())->setProperty(ObjProperty::STRUCTURE_CLEAR_VISITORS, NumericID(0));
break;
case ObjProperty::STRUCTURE_ADD_GARRISONED_HERO: //add garrisoned hero to visitors
rewardableBuildings.at(identifier.getNum())->setProperty(ObjProperty::VISITORS, garrisonHero->id);
rewardableBuildings.at(identifier.getNum())->setProperty(ObjProperty::VISITORS, getGarrisonHero()->id);
break;
case ObjProperty::BONUS_VALUE_FIRST:
bonusValue.first = identifier.getNum();
@ -296,7 +296,7 @@ int CGTownInstance::spellsAtLevel(int level, bool checkGuild) const
bool CGTownInstance::needsLastStack() const
{
return garrisonHero != nullptr;
return getGarrisonHero() != nullptr;
}
void CGTownInstance::setOwner(const PlayerColor & player) const
@ -309,13 +309,13 @@ void CGTownInstance::onHeroVisit(const CGHeroInstance * h) const
{
if(cb->gameState()->getPlayerRelations( getOwner(), h->getOwner() ) == PlayerRelations::ENEMIES)
{
if(armedGarrison() || visitingHero)
if(armedGarrison() || getVisitingHero())
{
const CGHeroInstance * defendingHero = visitingHero ? visitingHero : garrisonHero;
const CGHeroInstance * defendingHero = getVisitingHero() ? getVisitingHero() : getGarrisonHero();
const CArmedInstance * defendingArmy = defendingHero ? (CArmedInstance *)defendingHero : this;
const bool isBattleOutside = isBattleOutsideTown(defendingHero);
if(!isBattleOutside && visitingHero && defendingHero == visitingHero)
if(!isBattleOutside && getVisitingHero() && defendingHero == getVisitingHero())
{
//we have two approaches to merge armies: mergeGarrisonOnSiege() and used in the CGameHandler::garrisonSwap(ObjectInstanceID tid)
auto * nodeSiege = defendingHero->whereShouldBeAttachedOnSiege(isBattleOutside);
@ -323,7 +323,7 @@ void CGTownInstance::onHeroVisit(const CGHeroInstance * h) const
if(nodeSiege == (CBonusSystemNode *)this)
cb->swapGarrisonOnSiege(this->id);
const_cast<CGHeroInstance *>(defendingHero)->inTownGarrison = false; //hack to return visitor from garrison after battle
const_cast<CGHeroInstance *>(defendingHero)->setVisitedTown(this, false); //hack to return visitor from garrison after battle
}
cb->startBattle(h, defendingArmy, getSightCenter(), h, defendingHero, BattleLayout::createDefaultLayout(cb, h, defendingArmy), (isBattleOutside ? nullptr : this));
}
@ -343,7 +343,7 @@ void CGTownInstance::onHeroVisit(const CGHeroInstance * h) const
else
{
assert(h->visitablePos() == this->visitablePos());
bool commander_recover = h->commander && !h->commander->alive;
bool commander_recover = h->getCommander() && !h->getCommander()->alive;
if (commander_recover) // rise commander from dead
{
SetCommanderProperty scp;
@ -358,8 +358,8 @@ void CGTownInstance::onHeroVisit(const CGHeroInstance * h) const
{
InfoWindow iw;
iw.player = h->tempOwner;
iw.text.appendRawString(h->commander->getName());
iw.components.emplace_back(ComponentType::CREATURE, h->commander->getId(), h->commander->getCount());
iw.text.appendRawString(h->getCommander()->getName());
iw.components.emplace_back(ComponentType::CREATURE, h->getCommander()->getId(), h->getCommander()->getCount());
cb->showInfoDialog(&iw);
}
}
@ -368,7 +368,7 @@ void CGTownInstance::onHeroVisit(const CGHeroInstance * h) const
void CGTownInstance::onHeroLeave(const CGHeroInstance * h) const
{
//FIXME: find out why this issue appears on random maps
if(visitingHero == h)
if(getVisitingHero() == h)
{
cb->stopHeroVisitCastle(this, h);
logGlobal->trace("%s correctly left town %s", h->getNameTranslated(), getNameTranslated());
@ -584,13 +584,13 @@ void CGTownInstance::mergeGarrisonOnSiege() const
auto getWeakestStackSlot = [&](ui64 powerLimit)
{
std::vector<SlotID> weakSlots;
auto stacksList = visitingHero->stacks;
auto stacksList = getVisitingHero()->stacks;
std::pair<SlotID, CStackInstance *> pair;
while(!stacksList.empty())
{
pair = *vstd::minElementByFun(stacksList, [&](const std::pair<SlotID, CStackInstance *> & elem) { return elem.second->getPower(); });
if(powerLimit > pair.second->getPower() &&
(weakSlots.empty() || pair.second->getPower() == visitingHero->getStack(weakSlots.front()).getPower()))
(weakSlots.empty() || pair.second->getPower() == getVisitingHero()->getStack(weakSlots.front()).getPower()))
{
weakSlots.push_back(pair.first);
stacksList.erase(pair.first);
@ -612,20 +612,20 @@ void CGTownInstance::mergeGarrisonOnSiege() const
auto pair = *vstd::maxElementByFun(stacks, [&](const std::pair<SlotID, CStackInstance *> & elem)
{
ui64 power = elem.second->getPower();
auto dst = visitingHero->getSlotFor(elem.second->getCreatureID());
if(dst.validSlot() && visitingHero->hasStackAtSlot(dst))
power += visitingHero->getStack(dst).getPower();
auto dst = getVisitingHero()->getSlotFor(elem.second->getCreatureID());
if(dst.validSlot() && getVisitingHero()->hasStackAtSlot(dst))
power += getVisitingHero()->getStack(dst).getPower();
return power;
});
auto dst = visitingHero->getSlotFor(pair.second->getCreatureID());
auto dst = getVisitingHero()->getSlotFor(pair.second->getCreatureID());
if(dst.validSlot())
cb->moveStack(StackLocation(id, pair.first), StackLocation(visitingHero->id, dst), -1);
cb->moveStack(StackLocation(id, pair.first), StackLocation(getVisitingHero()->id, dst), -1);
else
{
dst = getWeakestStackSlot(static_cast<int>(pair.second->getPower()));
if(dst.validSlot())
cb->swapStacks(StackLocation(id, pair.first), StackLocation(visitingHero->id, dst));
cb->swapStacks(StackLocation(id, pair.first), StackLocation(getVisitingHero()->id, dst));
}
}
}
@ -722,10 +722,10 @@ void CGTownInstance::deserializationFix()
//Hero is already handled by CGameState::attachArmedObjects
// if(visitingHero)
// visitingHero->attachTo(&townAndVis);
// if(garrisonHero)
// garrisonHero->attachTo(this);
// if(getVisitingHero())
// getVisitingHero()->attachTo(&townAndVis);
// if(getGarrisonHero())
// getGarrisonHero()->attachTo(this);
}
void CGTownInstance::updateMoraleBonusFromArmy()
@ -737,7 +737,7 @@ void CGTownInstance::updateMoraleBonusFromArmy()
addNewBonus(b);
}
if (garrisonHero)
if (getGarrisonHero())
{
b->val = 0;
nodeHasChanged();
@ -786,7 +786,7 @@ void CGTownInstance::recreateBuildingsBonuses()
void CGTownInstance::setVisitingHero(CGHeroInstance *h)
{
if(visitingHero.get() == h)
if(getVisitingHero() == h)
return;
if(h)
@ -795,23 +795,23 @@ void CGTownInstance::setVisitingHero(CGHeroInstance *h)
assert(p);
h->detachFrom(*p);
h->attachTo(townAndVis);
visitingHero = h;
h->visitedTown = this;
h->inTownGarrison = false;
h->setVisitedTown(this, false);
visitingHero = h->id;
}
else
{
PlayerState *p = cb->gameState()->getPlayerState(visitingHero->tempOwner);
visitingHero->visitedTown = nullptr;
visitingHero->detachFrom(townAndVis);
visitingHero->attachTo(*p);
visitingHero = nullptr;
auto oldVisitor = dynamic_cast<CGHeroInstance*>(cb->gameState()->getObjInstance(visitingHero));
PlayerState *p = cb->gameState()->getPlayerState(getVisitingHero()->tempOwner);
oldVisitor->setVisitedTown(nullptr, false);
oldVisitor->detachFrom(townAndVis);
oldVisitor->attachTo(*p);
visitingHero = {};
}
}
void CGTownInstance::setGarrisonedHero(CGHeroInstance *h)
{
if(garrisonHero.get() == h)
if(getGarrisonHero() == h)
return;
if(h)
@ -820,25 +820,40 @@ void CGTownInstance::setGarrisonedHero(CGHeroInstance *h)
assert(p);
h->detachFrom(*p);
h->attachTo(*this);
garrisonHero = h;
h->visitedTown = this;
h->inTownGarrison = true;
h->setVisitedTown(this, true);
garrisonHero = h->id;
}
else
{
PlayerState *p = cb->gameState()->getPlayerState(garrisonHero->tempOwner);
garrisonHero->visitedTown = nullptr;
garrisonHero->inTownGarrison = false;
garrisonHero->detachFrom(*this);
garrisonHero->attachTo(*p);
garrisonHero = nullptr;
PlayerState *p = cb->gameState()->getPlayerState(getGarrisonHero()->tempOwner);
auto oldVisitor = dynamic_cast<CGHeroInstance*>(cb->gameState()->getObjInstance(visitingHero));
oldVisitor->setVisitedTown(nullptr, false);
oldVisitor->detachFrom(*this);
oldVisitor->attachTo(*p);
garrisonHero = {};
}
updateMoraleBonusFromArmy(); //avoid giving morale bonus for same army twice
}
const CGHeroInstance * CGTownInstance::getVisitingHero() const
{
if (!visitingHero.hasValue())
return nullptr;
return cb->getHero(visitingHero);
}
const CGHeroInstance * CGTownInstance::getGarrisonHero() const
{
if (!garrisonHero.hasValue())
return nullptr;
return cb->getHero(garrisonHero);
}
bool CGTownInstance::armedGarrison() const
{
return !stacks.empty() || garrisonHero;
return !stacks.empty() || getGarrisonHero();
}
int CGTownInstance::getTownLevel() const
@ -876,8 +891,8 @@ void CGTownInstance::setNameTextId( const std::string & newName )
const CArmedInstance * CGTownInstance::getUpperArmy() const
{
if(garrisonHero)
return garrisonHero;
if(getGarrisonHero())
return getGarrisonHero();
return this;
}
@ -1014,9 +1029,9 @@ CBuilding::TRequired CGTownInstance::genBuildingRequirements(const BuildingID &
void CGTownInstance::addHeroToStructureVisitors(const CGHeroInstance *h, si64 structureInstanceID ) const
{
if(visitingHero == h)
if(getVisitingHero() == h)
cb->setObjPropertyValue(id, ObjProperty::STRUCTURE_ADD_VISITING_HERO, structureInstanceID); //add to visitors
else if(garrisonHero == h)
else if(getGarrisonHero() == h)
cb->setObjPropertyValue(id, ObjProperty::STRUCTURE_ADD_GARRISONED_HERO, structureInstanceID); //then it must be garrisoned hero
else
{

View File

@ -11,7 +11,6 @@
#include "IMarket.h"
#include "CGDwelling.h"
#include "../ConstTransitivePtr.h"
#include "../entities/faction/CFaction.h" // TODO: remove
#include "../entities/faction/CTown.h" // TODO: remove
@ -57,13 +56,14 @@ class DLL_LINKAGE CGTownInstance : public CGDwelling, public IShipyard, public I
std::map<BuildingID, TownRewardableBuildingInstance*> convertOldBuildings(std::vector<TownRewardableBuildingInstance*> oldVector);
std::set<BuildingID> builtBuildings;
ObjectInstanceID garrisonHero;
ObjectInstanceID visitingHero;
public:
enum EFortLevel {NONE = 0, FORT = 1, CITADEL = 2, CASTLE = 3};
CTownAndVisitingHero townAndVis;
si32 built; //how many buildings has been built this turn
si32 destroyed; //how many buildings has been destroyed this turn
ConstTransitivePtr<CGHeroInstance> garrisonHero, visitingHero;
ui32 identifier; //special identifier from h3m (only > RoE maps)
PlayerColor alignmentToPlayer; // if set to non-neutral, random town will have same faction as specified player
std::set<BuildingID> forbiddenBuildings;
@ -115,6 +115,8 @@ public:
void setVisitingHero(CGHeroInstance *h);
void setGarrisonedHero(CGHeroInstance *h);
const CArmedInstance *getUpperArmy() const; //garrisoned hero if present or the town itself
const CGHeroInstance * getVisitingHero() const;
const CGHeroInstance * getGarrisonHero() const;
std::string getNameTranslated() const;
std::string getNameTextID() const;
@ -211,7 +213,7 @@ public:
inline bool isBattleOutsideTown(const CGHeroInstance * defendingHero) const
{
return defendingHero && garrisonHero && defendingHero != garrisonHero;
return defendingHero && getGarrisonHero() && defendingHero != getGarrisonHero();
}
protected:
void setPropertyDer(ObjProperty what, ObjPropertyID identifier) override;

View File

@ -616,7 +616,7 @@ bool CGWhirlpool::isProtected(const CGHeroInstance * h)
{
return h->hasBonusOfType(BonusType::WHIRLPOOL_PROTECTION)
|| (h->stacksCount() == 1 && h->Slots().begin()->second->count == 1)
|| (h->stacksCount() == 0 && h->commander && h->commander->alive);
|| (h->stacksCount() == 0 && h->getCommander() && h->getCommander()->alive);
}
ArtifactID CGArtifact::getArtifact() const

View File

@ -872,7 +872,7 @@ void SetSecSkill::applyGs(CGameState *gs)
void SetCommanderProperty::applyGs(CGameState *gs)
{
CCommanderInstance * commander = gs->getHero(heroid)->commander;
const auto & commander = gs->getHero(heroid)->getCommander();
assert (commander);
switch (which)
@ -1219,15 +1219,14 @@ void RemoveObject::applyGs(CGameState *gs)
return asi.artifact->getTypeId() == ArtifactID::GRAIL;
});
if(beatenHero->visitedTown)
if(beatenHero->getVisitedTown())
{
if(beatenHero->visitedTown->garrisonHero == beatenHero)
beatenHero->visitedTown->garrisonHero = nullptr;
if(beatenHero->getVisitedTown()->getGarrisonHero() == beatenHero)
beatenHero->getVisitedTown()->setGarrisonedHero(nullptr);
else
beatenHero->visitedTown->visitingHero = nullptr;
beatenHero->getVisitedTown()->setVisitingHero(nullptr);
beatenHero->visitedTown = nullptr;
beatenHero->inTownGarrison = false;
beatenHero->setVisitedTown(nullptr, false);
}
//return hero to the pool, so he may reappear in tavern
@ -1403,8 +1402,8 @@ void SetHeroesInTown::applyGs(CGameState *gs)
CGHeroInstance * v = gs->getHero(visiting);
CGHeroInstance * g = gs->getHero(garrison);
bool newVisitorComesFromGarrison = v && v == t->garrisonHero;
bool newGarrisonComesFromVisiting = g && g == t->visitingHero;
bool newVisitorComesFromGarrison = v && v == t->getGarrisonHero();
bool newGarrisonComesFromVisiting = g && g == t->getVisitingHero();
if(newVisitorComesFromGarrison)
t->setGarrisonedHero(nullptr);
@ -1493,7 +1492,7 @@ void GiveHero::applyGs(CGameState *gs)
gs->getPlayerState(h->getOwner())->addOwnedObject(h);
gs->getMap().addBlockVisTiles(h);
h->inTownGarrison = false;
h->setVisitedTown(nullptr, false);
}
void NewObject::applyGs(CGameState *gs)
@ -2032,7 +2031,7 @@ void CommanderLevelUp::applyGs(CGameState *gs)
{
auto * hero = gs->getHero(heroId);
assert(hero);
auto commander = hero->commander;
const auto & commander = hero->getCommander();
assert(commander);
commander->levelUp();
}
@ -2128,9 +2127,9 @@ void BattleResultAccepted::applyGs(CGameState *gs)
// Grow up growing artifacts
if(const auto winnerHero = gs->getHero(heroResult[winnerSide].heroId))
{
if(winnerHero->commander && winnerHero->commander->alive)
if(winnerHero->getCommander() && winnerHero->getCommander()->alive)
{
for(auto & art : winnerHero->commander->artifactsWorn)
for(auto & art : winnerHero->getCommander()->artifactsWorn)
art.second.artifact->growingUp();
}
for(auto & art : winnerHero->artifactsWorn)

View File

@ -268,7 +268,7 @@ TeleporterTilesVector CPathfinderHelper::getCastleGates(const PathNodeInfo & sou
for(const auto & town : getPlayerState(hero->tempOwner)->getTowns())
{
if(town->id != source.nodeObject->id && town->visitingHero == nullptr
if(town->id != source.nodeObject->id && town->getVisitingHero() == nullptr
&& town->hasBuilt(BuildingSubID::CASTLE_GATE))
{
allowedExits.push_back(town->visitablePos());

View File

@ -70,8 +70,8 @@ class BinaryDeserializer : public CLoaderBase
{
auto * hero = dynamic_cast<CGHeroInstance *>(armyPtr);
assert(hero);
assert(hero->commander);
data = hero->commander;
assert(hero->getCommander());
data = hero->getCommander();
}
return true;
}

View File

@ -43,7 +43,7 @@ bool AdventureSpellMechanics::canBeCast(spells::Problem & problem, const CGameIn
if (heroCaster)
{
if(heroCaster->inTownGarrison)
if(heroCaster->isGarrisoned())
return false;
const auto level = heroCaster->getSpellSchoolLevel(owner);
@ -467,7 +467,7 @@ ESpellCastResult TownPortalMechanics::applyAdventureEffects(SpellCastEnvironment
if(static_cast<int>(parameters.caster->getHeroCaster()->movementPointsRemaining()) < moveCost)
return ESpellCastResult::ERROR;
if(destination->visitingHero)
if(destination->getVisitingHero())
{
InfoWindow iw;
iw.player = parameters.caster->getCasterOwner();
@ -520,7 +520,7 @@ ESpellCastResult TownPortalMechanics::applyAdventureEffects(SpellCastEnvironment
return ESpellCastResult::ERROR;
}
if(destination->visitingHero)
if(destination->getVisitingHero())
{
env->complain("[Internal error] Can't teleport to occupied town");
return ESpellCastResult::ERROR;
@ -635,7 +635,7 @@ ESpellCastResult TownPortalMechanics::beginCast(SpellCastEnvironment * env, cons
for(const auto * t : towns)
{
if(t->visitingHero == nullptr) //empty town
if(t->getVisitingHero() == nullptr) //empty town
request.objects.push_back(t->id);
}

View File

@ -174,7 +174,7 @@ void setPlayerColor(QImage * sur, PlayerColor player)
std::shared_ptr<QImage> MapHandler::getObjectImage(const CGObjectInstance * obj)
{
if( !obj
|| (obj->ID==Obj::HERO && static_cast<const CGHeroInstance*>(obj)->inTownGarrison) //garrisoned hero
|| (obj->ID==Obj::HERO && static_cast<const CGHeroInstance*>(obj)->isGarrisoned()) //garrisoned hero
|| (obj->ID==Obj::BOAT && static_cast<const CGBoat*>(obj)->hero)) //boat with hero (hero graphics is used)
{
return nullptr;

View File

@ -334,8 +334,8 @@ void CGameHandler::expGiven(const CGHeroInstance *hero)
{
if (hero->gainsLevel())
levelUpHero(hero);
else if (hero->commander && hero->commander->gainsLevel())
levelUpCommander(hero->commander);
else if (hero->getCommander() && hero->getCommander()->gainsLevel())
levelUpCommander(hero->getCommander());
//if (hero->commander && hero->level > hero->commander->level && hero->commander->gainsLevel())
// levelUpCommander(hero->commander);
@ -375,7 +375,7 @@ void CGameHandler::giveExperience(const CGHeroInstance * hero, TExpType amountTo
sendAndApply(sps);
//hero may level up
if (hero->commander && hero->commander->alive)
if (hero->getCommander() && hero->getCommander()->alive)
{
//FIXME: trim experience according to map limit?
SetCommanderProperty scp;
@ -412,8 +412,8 @@ void CGameHandler::changeSecSkill(const CGHeroInstance * hero, SecondarySkill wh
sss.abs = abs;
sendAndApply(sss);
if (hero->visitedTown)
giveSpells(hero->visitedTown, hero);
if (hero->getVisitedTown())
giveSpells(hero->getVisitedTown(), hero);
// Our scouting range may have changed - update it
if (hero->getOwner().isValidPlayer())
@ -893,7 +893,7 @@ bool CGameHandler::moveHero(ObjectInstanceID hid, int3 dst, EMovementMode moveme
if(distance(h->pos, dst) >= 1.5 && movementMode == EMovementMode::STANDARD)
return complainRet("Tiles " + h->pos.toString()+ " and "+ dst.toString() +" are not neighboring!");
if(h->inTownGarrison)
if(h->isGarrisoned())
return complainRet("Can not move garrisoned hero!");
if(h->movementPointsRemaining() < cost && dst != h->pos && movementMode == EMovementMode::STANDARD)
@ -1048,7 +1048,7 @@ bool CGameHandler::teleportHero(ObjectInstanceID hid, ObjectInstanceID dstid, ui
if (!h || !t)
COMPLAIN_RET("Invalid call to teleportHero!");
const CGTownInstance *from = h->visitedTown;
const CGTownInstance *from = h->getVisitedTown();
if (((h->getOwner() != t->getOwner())
&& complain("Cannot teleport hero to another player"))
@ -1186,7 +1186,7 @@ void CGameHandler::takeCreatures(ObjectInstanceID objid, const std::vector<CStac
void CGameHandler::heroVisitCastle(const CGTownInstance * obj, const CGHeroInstance * hero)
{
if (obj->visitingHero != hero && obj->garrisonHero != hero)
if (obj->getVisitingHero() != hero && obj->getGarrisonHero() != hero)
{
HeroVisitCastle vc;
vc.hid = hero->id;
@ -1196,8 +1196,8 @@ void CGameHandler::heroVisitCastle(const CGTownInstance * obj, const CGHeroInsta
}
visitCastleObjects(obj, hero);
if (obj->visitingHero && obj->garrisonHero)
useScholarSkill(obj->visitingHero->id, obj->garrisonHero->id);
if (obj->getVisitingHero() && obj->getGarrisonHero())
useScholarSkill(obj->getVisitingHero()->id, obj->getGarrisonHero()->id);
checkVictoryLossConditionsForPlayer(hero->tempOwner); //transported artifact?
}
@ -2073,10 +2073,10 @@ bool CGameHandler::buildStructure(ObjectInstanceID tid, BuildingID requestedID,
case CBuilding::BUILD_GRAIL :
if(requestedBuilding->mode == CBuilding::BUILD_GRAIL) //needs grail
{
if(!t->visitingHero || !t->visitingHero->hasArt(ArtifactID::GRAIL))
if(!t->getVisitingHero() || !t->getVisitingHero()->hasArt(ArtifactID::GRAIL))
COMPLAIN_RET("Cannot build this without grail!")
else
removeArtifact(ArtifactLocation(t->visitingHero->id, t->visitingHero->getArtPos(ArtifactID::GRAIL, false)));
removeArtifact(ArtifactLocation(t->getVisitingHero()->id, t->getVisitingHero()->getArtPos(ArtifactID::GRAIL, false)));
}
break;
}
@ -2123,10 +2123,10 @@ bool CGameHandler::buildStructure(ObjectInstanceID tid, BuildingID requestedID,
if(isMageGuild || isLibrary || (t->getFactionID() == ETownType::CONFLUX && buildingID == BuildingID::GRAIL))
{
if(t->visitingHero)
giveSpells(t,t->visitingHero);
if(t->garrisonHero)
giveSpells(t,t->garrisonHero);
if(t->getVisitingHero())
giveSpells(t,t->getVisitingHero());
if(t->getGarrisonHero())
giveSpells(t,t->getGarrisonHero());
}
};
@ -2201,10 +2201,10 @@ bool CGameHandler::buildStructure(ObjectInstanceID tid, BuildingID requestedID,
{
//garrison hero first - consistent with original H3 Mana Vortex and Battle Scholar Academy levelup windows order
std::vector<const CGHeroInstance *> visitors;
if (t->garrisonHero)
visitors.push_back(t->garrisonHero);
if (t->visitingHero)
visitors.push_back(t->visitingHero);
if (t->getGarrisonHero())
visitors.push_back(t->getGarrisonHero());
if (t->getVisitingHero())
visitors.push_back(t->getVisitingHero());
if (!visitors.empty())
visitCastleObjects(t, visitors);
@ -2233,12 +2233,12 @@ bool CGameHandler::visitTownBuilding(ObjectInstanceID tid, BuildingID bid)
return true;
}
if (t->rewardableBuildings.count(bid) && t->visitingHero && t->getTown()->buildings.at(bid)->manualHeroVisit)
if (t->rewardableBuildings.count(bid) && t->getVisitingHero() && t->getTown()->buildings.at(bid)->manualHeroVisit)
{
std::vector<BuildingID> buildingsToVisit;
std::vector<const CGHeroInstance*> visitors;
buildingsToVisit.push_back(bid);
visitors.push_back(t->visitingHero);
visitors.push_back(t->getVisitingHero());
auto visitQuery = std::make_shared<TownBuildingVisitQuery>(this, t, visitors, buildingsToVisit);
queries->addQuery(visitQuery);
return true;
@ -2316,10 +2316,10 @@ bool CGameHandler::spellResearch(ObjectInstanceID tid, SpellID spellAtSlot, bool
setResearchedSpells(t, level, spells, accepted);
if(t->visitingHero)
giveSpells(t, t->visitingHero);
if(t->garrisonHero)
giveSpells(t, t->garrisonHero);
if(t->getVisitingHero())
giveSpells(t, t->getVisitingHero());
if(t->getGarrisonHero())
giveSpells(t, t->getGarrisonHero());
return true;
}
@ -2342,7 +2342,7 @@ bool CGameHandler::recruitCreatures(ObjectInstanceID objid, ObjectInstanceID dst
if (town)
{
COMPLAIN_RET_FALSE_IF(town != army && !hero, "Cannot recruit: invalid destination!");
COMPLAIN_RET_FALSE_IF(hero != town->garrisonHero && hero != town->visitingHero, "Cannot recruit: can only recruit to town or hero in town!!");
COMPLAIN_RET_FALSE_IF(hero != town->getGarrisonHero() && hero != town->getVisitingHero(), "Cannot recruit: can only recruit to town or hero in town!!");
}
else
{
@ -2505,16 +2505,16 @@ bool CGameHandler::swapGarrisonOnSiege(ObjectInstanceID tid)
{
const CGTownInstance * town = getTown(tid);
if(!town->garrisonHero == !town->visitingHero)
if(!town->getGarrisonHero() == !town->getVisitingHero())
return false;
SetHeroesInTown intown;
intown.tid = tid;
if(town->garrisonHero) //garrison -> vising
if(town->getGarrisonHero()) //garrison -> vising
{
intown.garrison = ObjectInstanceID();
intown.visiting = town->garrisonHero->id;
intown.visiting = town->getGarrisonHero()->id;
}
else //visiting -> garrison
{
@ -2522,7 +2522,7 @@ bool CGameHandler::swapGarrisonOnSiege(ObjectInstanceID tid)
town->mergeGarrisonOnSiege();
intown.visiting = ObjectInstanceID();
intown.garrison = town->visitingHero->id;
intown.garrison = town->getVisitingHero()->id;
}
sendAndApply(intown);
return true;
@ -2531,29 +2531,29 @@ bool CGameHandler::swapGarrisonOnSiege(ObjectInstanceID tid)
bool CGameHandler::garrisonSwap(ObjectInstanceID tid)
{
const CGTownInstance * town = getTown(tid);
if (!town->garrisonHero && town->visitingHero) //visiting => garrison, merge armies: town army => hero army
if (!town->getGarrisonHero() && town->getVisitingHero()) //visiting => garrison, merge armies: town army => hero army
{
if (!town->visitingHero->canBeMergedWith(*town))
if (!town->getVisitingHero()->canBeMergedWith(*town))
{
complain("Cannot make garrison swap, not enough free slots!");
return false;
}
moveArmy(town, town->visitingHero, true);
moveArmy(town, town->getVisitingHero(), true);
SetHeroesInTown intown;
intown.tid = tid;
intown.visiting = ObjectInstanceID();
intown.garrison = town->visitingHero->id;
intown.garrison = town->getVisitingHero()->id;
sendAndApply(intown);
return true;
}
else if (town->garrisonHero && !town->visitingHero) //move hero out of the garrison
else if (town->getGarrisonHero() && !town->getVisitingHero()) //move hero out of the garrison
{
int mapCap = getSettings().getInteger(EGameSettings::HEROES_PER_PLAYER_ON_MAP_CAP);
//check if moving hero out of town will break wandering heroes limit
if (getHeroCount(town->garrisonHero->tempOwner,false) >= mapCap)
if (getHeroCount(town->getGarrisonHero()->tempOwner,false) >= mapCap)
{
complain("Cannot move hero out of the garrison, there are already " + std::to_string(mapCap) + " wandering heroes!");
return false;
@ -2562,16 +2562,16 @@ bool CGameHandler::garrisonSwap(ObjectInstanceID tid)
SetHeroesInTown intown;
intown.tid = tid;
intown.garrison = ObjectInstanceID();
intown.visiting = town->garrisonHero->id;
intown.visiting = town->getGarrisonHero()->id;
sendAndApply(intown);
return true;
}
else if (!!town->garrisonHero && town->visitingHero) //swap visiting and garrison hero
else if (!!town->getGarrisonHero() && town->getVisitingHero()) //swap visiting and garrison hero
{
SetHeroesInTown intown;
intown.tid = tid;
intown.garrison = town->visitingHero->id;
intown.visiting = town->garrisonHero->id;
intown.garrison = town->getVisitingHero()->id;
intown.visiting = town->getGarrisonHero()->id;
sendAndApply(intown);
return true;
}
@ -2991,7 +2991,7 @@ bool CGameHandler::buyArtifact(ObjectInstanceID hid, ArtifactID aid)
{
const CGHeroInstance * hero = getHero(hid);
COMPLAIN_RET_FALSE_IF(nullptr == hero, "Invalid hero index");
const CGTownInstance * town = hero->visitedTown;
const CGTownInstance * town = hero->getVisitedTown();
COMPLAIN_RET_FALSE_IF(nullptr == town, "Hero not in town");
if (aid==ArtifactID::SPELLBOOK)
@ -3342,13 +3342,13 @@ bool CGameHandler::isAllowedExchange(ObjectInstanceID id1, ObjectInstanceID id2)
if (o1->ID == Obj::TOWN)
{
const CGTownInstance *t = static_cast<const CGTownInstance*>(o1);
if (t->visitingHero == o2 || t->garrisonHero == o2)
if (t->getVisitingHero() == o2 || t->getGarrisonHero() == o2)
return true;
}
if (o2->ID == Obj::TOWN)
{
const CGTownInstance *t = static_cast<const CGTownInstance*>(o2);
if (t->visitingHero == o1 || t->garrisonHero == o1)
if (t->getVisitingHero() == o1 || t->getGarrisonHero() == o1)
return true;
}
@ -3364,7 +3364,7 @@ bool CGameHandler::isAllowedExchange(ObjectInstanceID id1, ObjectInstanceID id2)
const CGHeroInstance *h2 = static_cast<const CGHeroInstance*>(o2);
// two heroes in same town (garrisoned and visiting)
if (h1->visitedTown != nullptr && h2->visitedTown != nullptr && h1->visitedTown == h2->visitedTown)
if (h1->getVisitedTown() != nullptr && h2->getVisitedTown() != nullptr && h1->getVisitedTown() == h2->getVisitedTown())
return true;
}
@ -3408,7 +3408,7 @@ void CGameHandler::objectVisited(const CGObjectInstance * obj, const CGHeroInsta
if(obj->ID == Obj::HERO)
{
auto visitedHero = static_cast<const CGHeroInstance *>(obj);
const auto visitedTown = visitedHero->visitedTown;
const auto visitedTown = visitedHero->getVisitedTown();
if(visitedTown)
{

View File

@ -183,7 +183,7 @@ void ApplyGhNetPackVisitor::visitUpgradeCreature(UpgradeCreature & pack)
void ApplyGhNetPackVisitor::visitGarrisonHeroSwap(GarrisonHeroSwap & pack)
{
const CGTownInstance * town = gh.getTown(pack.tid);
if(!gh.isPlayerOwns(connection, &pack, pack.tid) && !(town->garrisonHero && gh.isPlayerOwns(connection, &pack, town->garrisonHero->id)))
if(!gh.isPlayerOwns(connection, &pack, pack.tid) && !(town->getGarrisonHero() && gh.isPlayerOwns(connection, &pack, town->getGarrisonHero()->id)))
gh.throwNotAllowedAction(connection); //neither town nor garrisoned hero (if present) is ours
gh.throwIfPlayerNotActive(connection, &pack);

View File

@ -106,7 +106,7 @@ CasualtiesAfterBattle::CasualtiesAfterBattle(const CBattleInfoCallback & battle,
if(c)
{
auto h = dynamic_cast <const CGHeroInstance *>(army);
if(h && h->commander == c && (st->getCount() == 0 || !st->alive()))
if(h && h->getCommander() == c && (st->getCount() == 0 || !st->alive()))
{
logGlobal->debug("Commander is dead.");
heroWithDeadCommander = army->id; //TODO: unify commander handling
@ -323,11 +323,11 @@ void BattleResultProcessor::endBattleConfirm(const CBattleInfoCallback & battle)
if(battleResult->winner == BattleSide::DEFENDER
&& winnerHero
&& winnerHero->visitedTown
&& !winnerHero->inTownGarrison
&& winnerHero->visitedTown->garrisonHero == winnerHero)
&& winnerHero->getVisitedTown()
&& !winnerHero->isGarrisoned()
&& winnerHero->getVisitedTown()->getGarrisonHero() == winnerHero)
{
gameHandler->swapGarrisonOnSiege(winnerHero->visitedTown->id); //return defending visitor from garrison to its rightful place
gameHandler->swapGarrisonOnSiege(winnerHero->getVisitedTown()->id); //return defending visitor from garrison to its rightful place
}
//give exp
if(!finishingBattle->isDraw() && battleResult->exp[finishingBattle->winnerSide] && winnerHero)
@ -336,7 +336,7 @@ void BattleResultProcessor::endBattleConfirm(const CBattleInfoCallback & battle)
// Add statistics
if(loserHero && !finishingBattle->isDraw())
{
ConstTransitivePtr<CGHeroInstance> strongestHero = nullptr;
const CGHeroInstance * strongestHero = nullptr;
for(auto & hero : gameHandler->gameState()->getPlayerState(finishingBattle->loser)->getHeroes())
if(!strongestHero || hero->exp > strongestHero->exp)
strongestHero = hero;
@ -460,11 +460,11 @@ void BattleResultProcessor::battleFinalize(const BattleID & battleID, const Batt
addArtifactToTransfer(packHero, loserHero->getArtPos(art), art);
}
if(loserHero->commander)
if(loserHero->getCommander())
{
auto & packCommander = resultsApplied.artifacts.emplace_back(finishingBattle->victor, finishingBattle->loserId, finishingBattle->winnerId, false);
packCommander.srcCreature = loserHero->findStack(loserHero->commander);
for(const auto & artSlot : loserHero->commander->artifactsWorn)
packCommander.srcCreature = loserHero->findStack(loserHero->getCommander());
for(const auto & artSlot : loserHero->getCommander()->artifactsWorn)
addArtifactToTransfer(packCommander, artSlot.first, artSlot.second.getArt());
}
auto armyObj = dynamic_cast<const CArmedInstance*>(gameHandler->getObj(finishingBattle->loserId));

View File

@ -185,7 +185,7 @@ bool HeroPoolProcessor::hireHero(const ObjectInstanceID & objectID, const HeroTy
if(!town->hasBuilt(BuildingID::TAVERN) && gameHandler->complain("No tavern!"))
return false;
if(town->visitingHero && gameHandler->complain("There is visiting hero - no place!"))
if(town->getVisitingHero() && gameHandler->complain("There is visiting hero - no place!"))
return false;
}

View File

@ -143,11 +143,11 @@ void NewTurnProcessor::onPlayerTurnStarted(PlayerColor which)
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)
gameHandler->objectVisited(t, t->garrisonHero);
if (t->getGarrisonHero() != nullptr)
gameHandler->objectVisited(t, t->getGarrisonHero());
if (t->visitingHero != nullptr)
gameHandler->objectVisited(t, t->visitingHero);
if (t->getVisitingHero() != nullptr)
gameHandler->objectVisited(t, t->getVisitingHero());
}
}

View File

@ -773,7 +773,7 @@ void PlayerMessageProcessor::executeCheatCode(const std::string & cheatName, Pla
const CGHeroInstance * hero = gameHandler->getHero(currObj);
const CGTownInstance * town = gameHandler->getTown(currObj);
if (!town && hero)
town = hero->visitedTown;
town = hero->getVisitedTown();
const auto & doCheatGiveSpells = [&]() { cheatGiveSpells(player, hero); };
const auto & doCheatBuildTown = [&]() { cheatBuildTown(player, town); };

View File

@ -237,7 +237,7 @@ void CCommanderLevelUpDialogQuery::onRemoval(PlayerColor color)
{
assert(answer);
logGlobal->trace("Completing commander level-up query. Commander of hero %s gains skill %s", hero->getObjectName(), answer.value());
gh->levelUpCommander(hero->commander, clu.skills[*answer]);
gh->levelUpCommander(hero->getCommander(), clu.skills[*answer]);
}
void CCommanderLevelUpDialogQuery::notifyObjectAboutRemoval(const CGObjectInstance * visitedObject, const CGHeroInstance * visitingHero) const