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:
parent
62234fcf92
commit
417ea6451a
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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)));
|
||||
|
@ -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))
|
||||
|
@ -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;
|
||||
|
@ -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)));
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ TSubgoal BuildThis::whatToDoToAchieve()
|
||||
|
||||
// find town if not set
|
||||
if(!town && hero)
|
||||
town = hero->visitedTown;
|
||||
town = hero->getVisitedTown();
|
||||
|
||||
if(!town)
|
||||
{
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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()
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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());
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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));
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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); };
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user