mirror of
https://github.com/vcmi/vcmi.git
synced 2025-06-06 23:26:26 +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)
|
switch(obj->ID)
|
||||||
{
|
{
|
||||||
case Obj::TOWN:
|
case Obj::TOWN:
|
||||||
if(h->visitedTown) //we are inside, not just attacking
|
if(h->getVisitedTown()) //we are inside, not just attacking
|
||||||
{
|
{
|
||||||
makePossibleUpgrades(h.get());
|
makePossibleUpgrades(h.get());
|
||||||
|
|
||||||
std::unique_lock lockGuard(nullkiller->aiStateMutex);
|
std::unique_lock lockGuard(nullkiller->aiStateMutex);
|
||||||
|
|
||||||
if(!h->visitedTown->garrisonHero || !nullkiller->isHeroLocked(h->visitedTown->garrisonHero))
|
if(!h->getVisitedTown()->getGarrisonHero() || !nullkiller->isHeroLocked(h->getVisitedTown()->getGarrisonHero()))
|
||||||
moveCreaturesToHero(h->visitedTown);
|
moveCreaturesToHero(h->getVisitedTown());
|
||||||
|
|
||||||
if(nullkiller->heroManager->getHeroRole(h) == HeroRole::MAIN && !h->hasSpellbook()
|
if(nullkiller->heroManager->getHeroRole(h) == HeroRole::MAIN && !h->hasSpellbook()
|
||||||
&& nullkiller->getFreeGold() >= GameConstants::SPELLBOOK_GOLD_COST)
|
&& 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);
|
cb->buyArtifact(h.get(), ArtifactID::SPELLBOOK);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -929,9 +929,9 @@ void AIGateway::performObjectInteraction(const CGObjectInstance * obj, HeroPtr h
|
|||||||
|
|
||||||
void AIGateway::moveCreaturesToHero(const CGTownInstance * t)
|
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)
|
bool AIGateway::moveHeroToTile(int3 dst, HeroPtr h)
|
||||||
{
|
{
|
||||||
if(h->inTownGarrison && h->visitedTown)
|
if(h->isGarrisoned() && h->getVisitedTown())
|
||||||
{
|
{
|
||||||
cb->swapGarrisonHero(h->visitedTown);
|
cb->swapGarrisonHero(h->getVisitedTown());
|
||||||
moveCreaturesToHero(h->visitedTown);
|
moveCreaturesToHero(h->getVisitedTown());
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: consider if blockVisit objects change something in our checks: AIUtility::isBlockVisitObj()
|
//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)
|
void AIGateway::buildArmyIn(const CGTownInstance * t)
|
||||||
{
|
{
|
||||||
makePossibleUpgrades(t->visitingHero);
|
makePossibleUpgrades(t->getVisitingHero());
|
||||||
makePossibleUpgrades(t);
|
makePossibleUpgrades(t);
|
||||||
recruitCreatures(t, t->getUpperArmy());
|
recruitCreatures(t, t->getUpperArmy());
|
||||||
moveCreaturesToHero(t);
|
moveCreaturesToHero(t);
|
||||||
|
@ -767,7 +767,7 @@ bool shouldVisit(const Nullkiller * ai, const CGHeroInstance * h, const CGObject
|
|||||||
bool townHasFreeTavern(const CGTownInstance * town)
|
bool townHasFreeTavern(const CGTownInstance * town)
|
||||||
{
|
{
|
||||||
if(!town->hasBuilt(BuildingID::TAVERN)) return false;
|
if(!town->hasBuilt(BuildingID::TAVERN)) return false;
|
||||||
if(!town->visitingHero) return true;
|
if(!town->getVisitingHero()) return true;
|
||||||
|
|
||||||
bool canMoveVisitingHeroToGarrison = !town->getUpperArmy()->stacksCount();
|
bool canMoveVisitingHeroToGarrison = !town->getUpperArmy()->stacksCount();
|
||||||
|
|
||||||
@ -778,9 +778,9 @@ uint64_t getHeroArmyStrengthWithCommander(const CGHeroInstance * hero, const CCr
|
|||||||
{
|
{
|
||||||
auto armyStrength = heroArmy->getArmyStrength(fortLevel);
|
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;
|
return armyStrength;
|
||||||
|
@ -93,8 +93,8 @@ void DangerHitMapAnalyzer::updateHitMap()
|
|||||||
{
|
{
|
||||||
auto town = dynamic_cast<const CGTownInstance *>(obj);
|
auto town = dynamic_cast<const CGTownInstance *>(obj);
|
||||||
|
|
||||||
if(town->garrisonHero)
|
if(town->getGarrisonHero())
|
||||||
heroes[town->garrisonHero->tempOwner][town->garrisonHero] = HeroRole::MAIN;
|
heroes[town->getGarrisonHero()->tempOwner][town->getGarrisonHero()] = HeroRole::MAIN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -293,7 +293,7 @@ const CGHeroInstance * HeroManager::findWeakHeroToDismiss(uint64_t armyLimit, co
|
|||||||
|| existingHero->getArmyStrength() >armyLimit
|
|| existingHero->getArmyStrength() >armyLimit
|
||||||
|| getHeroRole(existingHero) == HeroRole::MAIN
|
|| getHeroRole(existingHero) == HeroRole::MAIN
|
||||||
|| existingHero->movementPointsRemaining()
|
|| existingHero->movementPointsRemaining()
|
||||||
|| (townToSpare != nullptr && existingHero->visitedTown == townToSpare)
|
|| (townToSpare != nullptr && existingHero->getVisitedTown() == townToSpare)
|
||||||
|| existingHero->artifactsWorn.size() > (existingHero->hasSpellbook() ? 2 : 1))
|
|| existingHero->artifactsWorn.size() > (existingHero->hasSpellbook() ? 2 : 1))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
|
@ -109,30 +109,30 @@ void handleCounterAttack(
|
|||||||
|
|
||||||
bool handleGarrisonHeroFromPreviousTurn(const CGTownInstance * town, Goals::TGoalVec & tasks, const Nullkiller * ai)
|
bool handleGarrisonHeroFromPreviousTurn(const CGTownInstance * town, Goals::TGoalVec & tasks, const Nullkiller * ai)
|
||||||
{
|
{
|
||||||
if(ai->isHeroLocked(town->garrisonHero.get()))
|
if(ai->isHeroLocked(town->getGarrisonHero()))
|
||||||
{
|
{
|
||||||
logAi->trace(
|
logAi->trace(
|
||||||
"Hero %s in garrison of town %s is supposed to defend the town",
|
"Hero %s in garrison of town %s is supposed to defend the town",
|
||||||
town->garrisonHero->getNameTranslated(),
|
town->getGarrisonHero()->getNameTranslated(),
|
||||||
town->getNameTranslated());
|
town->getNameTranslated());
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!town->visitingHero)
|
if(!town->getVisitingHero())
|
||||||
{
|
{
|
||||||
if(ai->cb->getHeroCount(ai->playerID, false) < GameConstants::MAX_HEROES_PER_PLAYER)
|
if(ai->cb->getHeroCount(ai->playerID, false) < GameConstants::MAX_HEROES_PER_PLAYER)
|
||||||
{
|
{
|
||||||
logAi->trace(
|
logAi->trace(
|
||||||
"Extracting hero %s from garrison of town %s",
|
"Extracting hero %s from garrison of town %s",
|
||||||
town->garrisonHero->getNameTranslated(),
|
town->getGarrisonHero()->getNameTranslated(),
|
||||||
town->getNameTranslated());
|
town->getNameTranslated());
|
||||||
|
|
||||||
tasks.push_back(Goals::sptr(Goals::ExchangeSwapTownHeroes(town, nullptr).setpriority(5)));
|
tasks.push_back(Goals::sptr(Goals::ExchangeSwapTownHeroes(town, nullptr).setpriority(5)));
|
||||||
|
|
||||||
return false;
|
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 armyDismissLimit = 1000;
|
||||||
auto heroToDismiss = ai->heroManager->findWeakHeroToDismiss(armyDismissLimit);
|
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
|
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;
|
return;
|
||||||
}
|
}
|
||||||
@ -233,16 +233,16 @@ void DefenceBehavior::evaluateDefence(Goals::TGoalVec & tasks, const CGTownInsta
|
|||||||
path.toString());
|
path.toString());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
auto townDefenseStrength = town->garrisonHero
|
auto townDefenseStrength = town->getGarrisonHero()
|
||||||
? town->garrisonHero->getTotalStrength()
|
? town->getGarrisonHero()->getTotalStrength()
|
||||||
: (town->visitingHero ? town->visitingHero->getTotalStrength() : town->getUpperArmy()->getArmyStrength());
|
: (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)
|
if(path.getHeroStrength() < townDefenseStrength)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if(town->garrisonHero && path.targetHero == town->garrisonHero.get())
|
else if(town->getGarrisonHero() && path.targetHero == town->getGarrisonHero())
|
||||||
{
|
{
|
||||||
if(path.getHeroStrength() < townDefenseStrength)
|
if(path.getHeroStrength() < townDefenseStrength)
|
||||||
continue;
|
continue;
|
||||||
@ -271,7 +271,7 @@ void DefenceBehavior::evaluateDefence(Goals::TGoalVec & tasks, const CGTownInsta
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(path.targetHero == town->visitingHero.get() && path.exchangeCount == 1)
|
if(path.targetHero == town->getVisitingHero() && path.exchangeCount == 1)
|
||||||
{
|
{
|
||||||
#if NKAI_TRACE_LEVEL >= 1
|
#if NKAI_TRACE_LEVEL >= 1
|
||||||
logAi->trace("Put %s to garrison of town %s",
|
logAi->trace("Put %s to garrison of town %s",
|
||||||
@ -280,7 +280,7 @@ void DefenceBehavior::evaluateDefence(Goals::TGoalVec & tasks, const CGTownInsta
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// dismiss creatures we are not able to pick to be able to hide in garrison
|
// 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
|
|| town->getUpperArmy()->stacksCount() == 0
|
||||||
|| path.targetHero->canBeMergedWith(*town)
|
|| path.targetHero->canBeMergedWith(*town)
|
||||||
|| (town->getUpperArmy()->getArmyStrength() < 500 && town->fortLevel() >= CGTownInstance::CITADEL))
|
|| (town->getUpperArmy()->getArmyStrength() < 500 && town->fortLevel() >= CGTownInstance::CITADEL))
|
||||||
@ -288,25 +288,25 @@ void DefenceBehavior::evaluateDefence(Goals::TGoalVec & tasks, const CGTownInsta
|
|||||||
tasks.push_back(
|
tasks.push_back(
|
||||||
Goals::sptr(Composition()
|
Goals::sptr(Composition()
|
||||||
.addNext(DefendTown(town, threat, path.targetHero))
|
.addNext(DefendTown(town, threat, path.targetHero))
|
||||||
.addNext(ExchangeSwapTownHeroes(town, town->visitingHero.get(), HeroLockedReason::DEFENCE))));
|
.addNext(ExchangeSwapTownHeroes(town, town->getVisitingHero(), HeroLockedReason::DEFENCE))));
|
||||||
}
|
}
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// main without army and visiting scout with army, very specific case
|
// main without army and visiting scout with army, very specific case
|
||||||
if(town->visitingHero && town->getUpperArmy()->stacksCount() == 0
|
if(town->getVisitingHero() && town->getUpperArmy()->stacksCount() == 0
|
||||||
&& path.targetHero != town->visitingHero.get() && path.exchangeCount == 1 && path.turn() == 0
|
&& path.targetHero != town->getVisitingHero() && path.exchangeCount == 1 && path.turn() == 0
|
||||||
&& ai->heroManager->evaluateHero(path.targetHero) > ai->heroManager->evaluateHero(town->visitingHero.get())
|
&& ai->heroManager->evaluateHero(path.targetHero) > ai->heroManager->evaluateHero(town->getVisitingHero())
|
||||||
&& 10 * path.targetHero->getTotalStrength() < town->visitingHero->getTotalStrength())
|
&& 10 * path.targetHero->getTotalStrength() < town->getVisitingHero()->getTotalStrength())
|
||||||
{
|
{
|
||||||
path.heroArmy = town->visitingHero.get();
|
path.heroArmy = town->getVisitingHero();
|
||||||
|
|
||||||
tasks.push_back(
|
tasks.push_back(
|
||||||
Goals::sptr(Composition()
|
Goals::sptr(Composition()
|
||||||
.addNext(DefendTown(town, threat, path))
|
.addNext(DefendTown(town, threat, path))
|
||||||
.addNextSequence({
|
.addNextSequence({
|
||||||
sptr(ExchangeSwapTownHeroes(town, town->visitingHero.get())),
|
sptr(ExchangeSwapTownHeroes(town, town->getVisitingHero())),
|
||||||
sptr(ExecuteHeroChain(path, town)),
|
sptr(ExecuteHeroChain(path, town)),
|
||||||
sptr(ExchangeSwapTownHeroes(town, path.targetHero, HeroLockedReason::DEFENCE))
|
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));
|
composition.addNext(DefendTown(town, threat, path));
|
||||||
TGoalVec sequence;
|
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));
|
tasks.push_back(Goals::sptr(composition));
|
||||||
|
|
||||||
#if NKAI_TRACE_LEVEL >= 1
|
#if NKAI_TRACE_LEVEL >= 1
|
||||||
logAi->trace("Locking hero %s in garrison of %s",
|
logAi->trace("Locking hero %s in garrison of %s",
|
||||||
town->garrisonHero.get()->getObjectName(),
|
town->getGarrisonHero()->getObjectName(),
|
||||||
town->getObjectName());
|
town->getObjectName());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
continue;
|
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
|
#if NKAI_TRACE_LEVEL >= 1
|
||||||
logAi->trace("Cancel moving %s to defend town %s as the town has garrison hero",
|
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)
|
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
|
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;
|
return;
|
||||||
|
|
||||||
if(town->hasBuilt(BuildingID::TAVERN)
|
if(town->hasBuilt(BuildingID::TAVERN)
|
||||||
@ -461,25 +461,25 @@ void DefenceBehavior::evaluateRecruitingHero(Goals::TGoalVec & tasks, const HitM
|
|||||||
bool needSwap = false;
|
bool needSwap = false;
|
||||||
const CGHeroInstance * heroToDismiss = nullptr;
|
const CGHeroInstance * heroToDismiss = nullptr;
|
||||||
|
|
||||||
if(town->visitingHero)
|
if(town->getVisitingHero())
|
||||||
{
|
{
|
||||||
if(!town->garrisonHero)
|
if(!town->getGarrisonHero())
|
||||||
needSwap = true;
|
needSwap = true;
|
||||||
else
|
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;
|
continue;
|
||||||
|
|
||||||
heroToDismiss = town->visitingHero.get();
|
heroToDismiss = town->getVisitingHero();
|
||||||
}
|
}
|
||||||
else if(town->garrisonHero->getArmyStrength() >= hero->getArmyStrength())
|
else if(town->getGarrisonHero()->getArmyStrength() >= hero->getArmyStrength())
|
||||||
continue;
|
continue;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
needSwap = true;
|
needSwap = true;
|
||||||
heroToDismiss = town->garrisonHero.get();
|
heroToDismiss = town->getGarrisonHero();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -499,7 +499,7 @@ void DefenceBehavior::evaluateRecruitingHero(Goals::TGoalVec & tasks, const HitM
|
|||||||
Goals::Composition recruitHeroComposition;
|
Goals::Composition recruitHeroComposition;
|
||||||
|
|
||||||
if(needSwap)
|
if(needSwap)
|
||||||
sequence.push_back(sptr(ExchangeSwapTownHeroes(town, town->visitingHero.get())));
|
sequence.push_back(sptr(ExchangeSwapTownHeroes(town, town->getVisitingHero())));
|
||||||
|
|
||||||
if(heroToDismiss)
|
if(heroToDismiss)
|
||||||
sequence.push_back(sptr(DismissHero(heroToDismiss)));
|
sequence.push_back(sptr(DismissHero(heroToDismiss)));
|
||||||
|
@ -167,21 +167,21 @@ Goals::TGoalVec GatherArmyBehavior::deliverArmyToHero(const Nullkiller * ai, con
|
|||||||
|
|
||||||
composition.addNext(heroExchange);
|
composition.addNext(heroExchange);
|
||||||
|
|
||||||
if(hero->inTownGarrison && path.turn() == 0)
|
if(hero->isGarrisoned() && path.turn() == 0)
|
||||||
{
|
{
|
||||||
auto lockReason = ai->getHeroLockedReason(hero);
|
auto lockReason = ai->getHeroLockedReason(hero);
|
||||||
|
|
||||||
if(path.targetHero->visitedTown == hero->visitedTown)
|
if(path.targetHero->getVisitedTown() == hero->getVisitedTown())
|
||||||
{
|
{
|
||||||
composition.addNextSequence({
|
composition.addNextSequence({
|
||||||
sptr(ExchangeSwapTownHeroes(hero->visitedTown, hero, lockReason))});
|
sptr(ExchangeSwapTownHeroes(hero->getVisitedTown(), hero, lockReason))});
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
composition.addNextSequence({
|
composition.addNextSequence({
|
||||||
sptr(ExchangeSwapTownHeroes(hero->visitedTown)),
|
sptr(ExchangeSwapTownHeroes(hero->getVisitedTown())),
|
||||||
sptr(exchangePath),
|
sptr(exchangePath),
|
||||||
sptr(ExchangeSwapTownHeroes(hero->visitedTown, hero, lockReason))});
|
sptr(ExchangeSwapTownHeroes(hero->getVisitedTown(), hero, lockReason))});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -262,7 +262,7 @@ Goals::TGoalVec GatherArmyBehavior::upgradeArmy(const Nullkiller * ai, const CGT
|
|||||||
continue;
|
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
|
#if NKAI_TRACE_LEVEL >= 2
|
||||||
logAi->trace("Ignore path. Town has visiting hero.");
|
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);
|
auto upgrade = ai->armyManager->calculateCreaturesUpgrade(path.heroArmy, upgrader, availableResources);
|
||||||
|
|
||||||
if(!upgrader->garrisonHero
|
if(!upgrader->getGarrisonHero()
|
||||||
&& (
|
&& (
|
||||||
hasMainAround
|
hasMainAround
|
||||||
|| ai->heroManager->getHeroRole(path.targetHero) == HeroRole::MAIN))
|
|| 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);
|
closestThreat = std::min(closestThreat, threat.turn);
|
||||||
}
|
}
|
||||||
//Don't hire a hero where there already is one present
|
//Don't hire a hero where there already is one present
|
||||||
if (town->visitingHero && town->garrisonHero)
|
if (town->getVisitingHero() && town->getGarrisonHero())
|
||||||
continue;
|
continue;
|
||||||
float visitability = 0;
|
float visitability = 0;
|
||||||
for (auto checkHero : ourHeroes)
|
for (auto checkHero : ourHeroes)
|
||||||
@ -98,7 +98,7 @@ Goals::TGoalVec RecruitHeroBehavior::decompose(const Nullkiller * ai) const
|
|||||||
|
|
||||||
for(auto hero : availableHeroes)
|
for(auto hero : availableHeroes)
|
||||||
{
|
{
|
||||||
if ((town->visitingHero || town->garrisonHero)
|
if ((town->getVisitingHero() || town->getGarrisonHero())
|
||||||
&& closestThreat < 1
|
&& closestThreat < 1
|
||||||
&& hero->getArmyCost() < GameConstants::HERO_GOLD_COST / 3.0)
|
&& hero->getArmyCost() < GameConstants::HERO_GOLD_COST / 3.0)
|
||||||
continue;
|
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
|
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 1;
|
||||||
|
|
||||||
return path.movementCost();
|
return path.movementCost();
|
||||||
@ -53,7 +53,7 @@ const CGHeroInstance * getNearestHero(const Nullkiller * ai, const CGTownInstanc
|
|||||||
if(shortestPath.nodes.size() > 1
|
if(shortestPath.nodes.size() > 1
|
||||||
|| shortestPath.turn() != 0
|
|| shortestPath.turn() != 0
|
||||||
|| shortestPath.targetHero->visitablePos().dist2dSQ(town->visitablePos()) > 4
|
|| shortestPath.targetHero->visitablePos().dist2dSQ(town->visitablePos()) > 4
|
||||||
|| (town->garrisonHero && shortestPath.targetHero == town->garrisonHero.get()))
|
|| (town->getGarrisonHero() && shortestPath.targetHero == town->getGarrisonHero()))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
return shortestPath.targetHero;
|
return shortestPath.targetHero;
|
||||||
@ -64,7 +64,7 @@ bool needToRecruitHero(const Nullkiller * ai, const CGTownInstance * startupTown
|
|||||||
if(!ai->heroManager->canRecruitHero(startupTown))
|
if(!ai->heroManager->canRecruitHero(startupTown))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if(!startupTown->garrisonHero && !startupTown->visitingHero)
|
if(!startupTown->getGarrisonHero() && !startupTown->getVisitingHero())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
int treasureSourcesCount = 0;
|
int treasureSourcesCount = 0;
|
||||||
@ -122,8 +122,8 @@ Goals::TGoalVec StartupBehavior::decompose(const Nullkiller * ai) const
|
|||||||
{
|
{
|
||||||
startupTown = *vstd::maxElementByFun(towns, [ai](const CGTownInstance * town) -> float
|
startupTown = *vstd::maxElementByFun(towns, [ai](const CGTownInstance * town) -> float
|
||||||
{
|
{
|
||||||
if(town->garrisonHero)
|
if(town->getGarrisonHero())
|
||||||
return ai->heroManager->evaluateHero(town->garrisonHero.get());
|
return ai->heroManager->evaluateHero(town->getGarrisonHero());
|
||||||
|
|
||||||
auto closestHero = getNearestHero(ai, town);
|
auto closestHero = getNearestHero(ai, town);
|
||||||
|
|
||||||
@ -147,7 +147,7 @@ Goals::TGoalVec StartupBehavior::decompose(const Nullkiller * ai) const
|
|||||||
|
|
||||||
if(closestHero)
|
if(closestHero)
|
||||||
{
|
{
|
||||||
if(!startupTown->visitingHero)
|
if(!startupTown->getVisitingHero())
|
||||||
{
|
{
|
||||||
if(ai->armyManager->howManyReinforcementsCanGet(startupTown->getUpperArmy(), startupTown->getUpperArmy(), closestHero, TerrainId::NONE) > 200)
|
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
|
else
|
||||||
{
|
{
|
||||||
auto visitingHero = startupTown->visitingHero.get();
|
auto visitingHero = startupTown->getVisitingHero();
|
||||||
auto visitingHeroScore = ai->heroManager->evaluateHero(visitingHero);
|
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);
|
auto garrisonHeroScore = ai->heroManager->evaluateHero(garrisonHero);
|
||||||
|
|
||||||
if(visitingHeroScore > garrisonHeroScore
|
if(visitingHeroScore > garrisonHeroScore
|
||||||
@ -187,7 +187,7 @@ Goals::TGoalVec StartupBehavior::decompose(const Nullkiller * ai) const
|
|||||||
else if(canRecruitHero)
|
else if(canRecruitHero)
|
||||||
{
|
{
|
||||||
auto canPickTownArmy = startupTown->stacksCount() == 0
|
auto canPickTownArmy = startupTown->stacksCount() == 0
|
||||||
|| ai->armyManager->howManyReinforcementsCanGet(startupTown->visitingHero, startupTown) > 0;
|
|| ai->armyManager->howManyReinforcementsCanGet(startupTown->getVisitingHero(), startupTown) > 0;
|
||||||
|
|
||||||
if(canPickTownArmy)
|
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)));
|
tasks.push_back(Goals::sptr(Goals::RecruitHero(startupTown)));
|
||||||
}
|
}
|
||||||
|
|
||||||
if(tasks.empty() && !startupTown->visitingHero)
|
if(tasks.empty() && !startupTown->getVisitingHero())
|
||||||
{
|
{
|
||||||
for(auto town : towns)
|
for(auto town : towns)
|
||||||
{
|
{
|
||||||
if(!town->visitingHero && needToRecruitHero(ai, town))
|
if(!town->getVisitingHero() && needToRecruitHero(ai, town))
|
||||||
{
|
{
|
||||||
tasks.push_back(Goals::sptr(Goals::RecruitHero(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)
|
for(const CGTownInstance * town : towns)
|
||||||
{
|
{
|
||||||
if(town->garrisonHero
|
if(town->getGarrisonHero()
|
||||||
&& town->garrisonHero->movementPointsRemaining()
|
&& town->getGarrisonHero()->movementPointsRemaining()
|
||||||
&& !town->visitingHero
|
&& !town->getVisitingHero()
|
||||||
&& ai->getHeroLockedReason(town->garrisonHero) != HeroLockedReason::DEFENCE)
|
&& ai->getHeroLockedReason(town->getGarrisonHero()) != HeroLockedReason::DEFENCE)
|
||||||
{
|
{
|
||||||
tasks.push_back(Goals::sptr(ExchangeSwapTownHeroes(town, nullptr).setpriority(MIN_PRIORITY)));
|
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)
|
for(auto & path : paths)
|
||||||
{
|
{
|
||||||
if(town->visitingHero && town->visitingHero.get() != path.targetHero)
|
if(town->getVisitingHero() && town->getVisitingHero() != path.targetHero)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if(!path.getFirstBlockedAction() && path.exchangeCount <= 1)
|
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);
|
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);
|
objectDanger *= ai->heroManager->getFightingStrengthCached(hero);
|
||||||
}
|
}
|
||||||
if (objWithID<Obj::TOWN>(dangerousObject))
|
if (objWithID<Obj::TOWN>(dangerousObject))
|
||||||
{
|
{
|
||||||
auto town = dynamic_cast<const CGTownInstance*>(dangerousObject);
|
auto town = dynamic_cast<const CGTownInstance*>(dangerousObject);
|
||||||
auto hero = town->garrisonHero;
|
auto hero = town->getGarrisonHero();
|
||||||
|
|
||||||
if (hero)
|
if (hero)
|
||||||
objectDanger *= ai->heroManager->getFightingStrengthCached(hero);
|
objectDanger *= ai->heroManager->getFightingStrengthCached(hero);
|
||||||
@ -121,7 +121,7 @@ ui64 FuzzyHelper::evaluateDanger(const CGObjectInstance * obj)
|
|||||||
const CGTownInstance * town = dynamic_cast<const CGTownInstance *>(obj);
|
const CGTownInstance * town = dynamic_cast<const CGTownInstance *>(obj);
|
||||||
auto danger = town->getUpperArmy()->getArmyStrength();
|
auto danger = town->getUpperArmy()->getArmyStrength();
|
||||||
|
|
||||||
if(danger || town->visitingHero)
|
if(danger || town->getVisitingHero())
|
||||||
{
|
{
|
||||||
auto fortLevel = town->fortLevel();
|
auto fortLevel = town->fortLevel();
|
||||||
|
|
||||||
|
@ -44,17 +44,17 @@ void AdventureSpellCast::accept(AIGateway * ai)
|
|||||||
{
|
{
|
||||||
ai->selectedObject = town->id;
|
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);
|
ai->myCb->swapGarrisonHero(town);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(town->visitingHero)
|
if(town->getVisitingHero())
|
||||||
throw cannotFulfillGoalException("The town is already occupied by " + town->visitingHero->getNameTranslated());
|
throw cannotFulfillGoalException("The town is already occupied by " + town->getVisitingHero()->getNameTranslated());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hero->inTownGarrison)
|
if (hero->isGarrisoned())
|
||||||
ai->myCb->swapGarrisonHero(hero->visitedTown);
|
ai->myCb->swapGarrisonHero(hero->getVisitedTown());
|
||||||
|
|
||||||
auto wait = cb->waitTillRealize;
|
auto wait = cb->waitTillRealize;
|
||||||
|
|
||||||
|
@ -97,9 +97,9 @@ void BuyArmy::accept(AIGateway * ai)
|
|||||||
throw cannotFulfillGoalException("No creatures to buy.");
|
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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,11 +30,11 @@ std::vector<ObjectInstanceID> ExchangeSwapTownHeroes::getAffectedObjects() const
|
|||||||
{
|
{
|
||||||
std::vector<ObjectInstanceID> affectedObjects = { town->id };
|
std::vector<ObjectInstanceID> affectedObjects = { town->id };
|
||||||
|
|
||||||
if(town->garrisonHero)
|
if(town->getGarrisonHero())
|
||||||
affectedObjects.push_back(town->garrisonHero->id);
|
affectedObjects.push_back(town->getGarrisonHero()->id);
|
||||||
|
|
||||||
if(town->visitingHero)
|
if(town->getVisitingHero())
|
||||||
affectedObjects.push_back(town->visitingHero->id);
|
affectedObjects.push_back(town->getVisitingHero()->id);
|
||||||
|
|
||||||
return affectedObjects;
|
return affectedObjects;
|
||||||
}
|
}
|
||||||
@ -42,8 +42,8 @@ std::vector<ObjectInstanceID> ExchangeSwapTownHeroes::getAffectedObjects() const
|
|||||||
bool ExchangeSwapTownHeroes::isObjectAffected(ObjectInstanceID id) const
|
bool ExchangeSwapTownHeroes::isObjectAffected(ObjectInstanceID id) const
|
||||||
{
|
{
|
||||||
return town->id == id
|
return town->id == id
|
||||||
|| (town->visitingHero && town->visitingHero->id == id)
|
|| (town->getVisitingHero() && town->getVisitingHero()->id == id)
|
||||||
|| (town->garrisonHero && town->garrisonHero->id == id);
|
|| (town->getGarrisonHero() && town->getGarrisonHero()->id == id);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ExchangeSwapTownHeroes::toString() const
|
std::string ExchangeSwapTownHeroes::toString() const
|
||||||
@ -58,39 +58,39 @@ bool ExchangeSwapTownHeroes::operator==(const ExchangeSwapTownHeroes & other) co
|
|||||||
|
|
||||||
void ExchangeSwapTownHeroes::accept(AIGateway * ai)
|
void ExchangeSwapTownHeroes::accept(AIGateway * ai)
|
||||||
{
|
{
|
||||||
if(!garrisonHero)
|
if(!getGarrisonHero())
|
||||||
{
|
{
|
||||||
auto currentGarrisonHero = town->garrisonHero;
|
auto currentGarrisonHero = town->getGarrisonHero();
|
||||||
|
|
||||||
if(!currentGarrisonHero)
|
if(!currentGarrisonHero)
|
||||||
throw cannotFulfillGoalException("Invalid configuration. There is no hero in town garrison.");
|
throw cannotFulfillGoalException("Invalid configuration. There is no hero in town garrison.");
|
||||||
|
|
||||||
cb->swapGarrisonHero(town);
|
cb->swapGarrisonHero(town);
|
||||||
|
|
||||||
if(currentGarrisonHero.get() != town->visitingHero.get())
|
if(currentGarrisonHero != town->getVisitingHero())
|
||||||
{
|
{
|
||||||
logAi->error("VisitingHero is empty, expected %s", currentGarrisonHero->getNameTranslated());
|
logAi->error("VisitingHero is empty, expected %s", currentGarrisonHero->getNameTranslated());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ai->buildArmyIn(town);
|
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());
|
logAi->debug("Extracted hero %s from garrison of %s", currentGarrisonHero->getNameTranslated(), town->getNameTranslated());
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(town->visitingHero && town->visitingHero.get() != garrisonHero)
|
if(town->getVisitingHero() && town->getVisitingHero() != getGarrisonHero())
|
||||||
cb->swapGarrisonHero(town);
|
cb->swapGarrisonHero(town);
|
||||||
|
|
||||||
ai->makePossibleUpgrades(town);
|
ai->makePossibleUpgrades(town);
|
||||||
ai->moveHeroToTile(town->visitablePos(), garrisonHero);
|
ai->moveHeroToTile(town->visitablePos(), getGarrisonHero());
|
||||||
|
|
||||||
auto upperArmy = town->getUpperArmy();
|
auto upperArmy = town->getUpperArmy();
|
||||||
|
|
||||||
if(!town->garrisonHero)
|
if(!town->getGarrisonHero())
|
||||||
{
|
{
|
||||||
if (!garrisonHero->canBeMergedWith(*town))
|
if (!getGarrisonHero()->canBeMergedWith(*town))
|
||||||
{
|
{
|
||||||
while (upperArmy->stacksCount() != 0)
|
while (upperArmy->stacksCount() != 0)
|
||||||
{
|
{
|
||||||
@ -103,16 +103,16 @@ void ExchangeSwapTownHeroes::accept(AIGateway * ai)
|
|||||||
|
|
||||||
if(lockingReason != HeroLockedReason::NOT_LOCKED)
|
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->nullkiller->unlockHero(town->getVisitingHero());
|
||||||
ai->makePossibleUpgrades(town->visitingHero);
|
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)
|
if(!heroToHire)
|
||||||
throw cannotFulfillGoalException("No hero to hire!");
|
throw cannotFulfillGoalException("No hero to hire!");
|
||||||
|
|
||||||
if(t->visitingHero)
|
if(t->getVisitingHero())
|
||||||
{
|
{
|
||||||
cb->swapGarrisonHero(t);
|
cb->swapGarrisonHero(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(t->visitingHero)
|
if(t->getVisitingHero())
|
||||||
throw cannotFulfillGoalException("Town " + t->nodeName() + " is occupied. Cannot recruit hero!");
|
throw cannotFulfillGoalException("Town " + t->nodeName() + " is occupied. Cannot recruit hero!");
|
||||||
|
|
||||||
cb->recruitHero(t, heroToHire);
|
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
|
// do not allow our own heroes in garrison to act on map
|
||||||
if(hero.first->getOwner() == ai->playerID
|
if(hero.first->getOwner() == ai->playerID
|
||||||
&& hero.first->inTownGarrison
|
&& hero.first->isGarrisoned()
|
||||||
&& (ai->isHeroLocked(hero.first) || ai->heroManager->heroCapReached(false)))
|
&& (ai->isHeroLocked(hero.first) || ai->heroManager->heroCapReached(false)))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
@ -987,9 +987,9 @@ void AINodeStorage::setTownsAndDwellings(
|
|||||||
{
|
{
|
||||||
uint64_t mask = FirstActorMask << actors.size();
|
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
|
// check defence imrove
|
||||||
if(!town->garrisonHero)
|
if(!town->getGarrisonHero())
|
||||||
{
|
{
|
||||||
actors.push_back(std::make_shared<TownGarrisonActor>(town, mask));
|
actors.push_back(std::make_shared<TownGarrisonActor>(town, mask));
|
||||||
}
|
}
|
||||||
@ -1185,19 +1185,19 @@ void AINodeStorage::calculateTownPortal(
|
|||||||
{
|
{
|
||||||
for(const CGTownInstance * targetTown : towns)
|
for(const CGTownInstance * targetTown : towns)
|
||||||
{
|
{
|
||||||
if(targetTown->visitingHero
|
if(targetTown->getVisitingHero()
|
||||||
&& targetTown->getUpperArmy()->stacksCount()
|
&& 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;
|
bool sameActorInTown = actor->chainMask == basicMask;
|
||||||
|
|
||||||
if(!sameActorInTown)
|
if(!sameActorInTown)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (targetTown->visitingHero
|
if (targetTown->getVisitingHero()
|
||||||
&& (targetTown->visitingHero.get()->getFactionID() != actor->hero->getFactionID()
|
&& (targetTown->getVisitingHero()->getFactionID() != actor->hero->getFactionID()
|
||||||
|| targetTown->getUpperArmy()->stacksCount()))
|
|| targetTown->getUpperArmy()->stacksCount()))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -20,13 +20,13 @@ namespace AIPathfinding
|
|||||||
{
|
{
|
||||||
void BuyArmyAction::execute(AIGateway * ai, const CGHeroInstance * hero) const
|
void BuyArmyAction::execute(AIGateway * ai, const CGHeroInstance * hero) const
|
||||||
{
|
{
|
||||||
if(!hero->visitedTown)
|
if(!hero->getVisitedTown())
|
||||||
{
|
{
|
||||||
throw cannotFulfillGoalException(
|
throw cannotFulfillGoalException(
|
||||||
hero->getNameTranslated() + " being at " + hero->visitablePos().toString() + " has no town to recruit creatures.");
|
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
|
std::string BuyArmyAction::toString() const
|
||||||
|
@ -39,8 +39,8 @@ TSubgoal AdventureSpellCast::whatToDoToAchieve()
|
|||||||
if(hero->mana < hero->getSpellCost(spell))
|
if(hero->mana < hero->getSpellCost(spell))
|
||||||
throw cannotFulfillGoalException("Hero has not enough mana to cast " + spell->getNameTranslated());
|
throw cannotFulfillGoalException("Hero has not enough mana to cast " + spell->getNameTranslated());
|
||||||
|
|
||||||
if(spellID == SpellID::TOWN_PORTAL && town && town->visitingHero)
|
if(spellID == SpellID::TOWN_PORTAL && town && town->getVisitingHero())
|
||||||
throw cannotFulfillGoalException("The town is already occupied by " + town->visitingHero->getNameTranslated());
|
throw cannotFulfillGoalException("The town is already occupied by " + town->getVisitingHero()->getNameTranslated());
|
||||||
|
|
||||||
return iAmElementar();
|
return iAmElementar();
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,7 @@ TSubgoal BuildThis::whatToDoToAchieve()
|
|||||||
|
|
||||||
// find town if not set
|
// find town if not set
|
||||||
if(!town && hero)
|
if(!town && hero)
|
||||||
town = hero->visitedTown;
|
town = hero->getVisitedTown();
|
||||||
|
|
||||||
if(!town)
|
if(!town)
|
||||||
{
|
{
|
||||||
|
@ -56,14 +56,14 @@ TGoalVec GatherArmy::getAllPossibleSubgoals()
|
|||||||
if(waysToVisit.size())
|
if(waysToVisit.size())
|
||||||
{
|
{
|
||||||
//grab army from town
|
//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))
|
if(!vstd::contains(ai->townVisitsThisWeek[hero], t))
|
||||||
vstd::concatenate(ret, waysToVisit);
|
vstd::concatenate(ret, waysToVisit);
|
||||||
}
|
}
|
||||||
|
|
||||||
//buy army in town
|
//buy army in town
|
||||||
if (!t->visitingHero || t->visitingHero == hero.get(true))
|
if (!t->getVisitingHero() || t->getVisitingHero() == hero.get(true))
|
||||||
{
|
{
|
||||||
std::vector<int> values = {
|
std::vector<int> values = {
|
||||||
value,
|
value,
|
||||||
|
@ -75,9 +75,9 @@ TGoalVec GatherTroops::getAllPossibleSubgoals()
|
|||||||
|
|
||||||
if(count >= this->value)
|
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
|
else
|
||||||
{
|
{
|
||||||
|
@ -83,9 +83,9 @@ TSubgoal Win::whatToDoToAchieve()
|
|||||||
if(auto h = ai->getHeroWithGrail())
|
if(auto h = ai->getHeroWithGrail())
|
||||||
{
|
{
|
||||||
//hero is in a town that can host Grail
|
//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));
|
return sptr(BuildThis(BuildingID::GRAIL, t).setpriority(10));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -267,7 +267,7 @@ void AINodeStorage::calculateTownPortalTeleportations(
|
|||||||
|
|
||||||
for(const CGTownInstance * targetTown : towns)
|
for(const CGTownInstance * targetTown : towns)
|
||||||
{
|
{
|
||||||
if(targetTown->visitingHero)
|
if(targetTown->getVisitingHero())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
auto nodeOptional = getOrCreateNode(targetTown->visitablePos(), EPathfindingLayer::LAND, srcNode->chainMask | CAST_CHAIN);
|
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)
|
void VCAI::heroCreated(const CGHeroInstance * h)
|
||||||
{
|
{
|
||||||
LOG_TRACE(logAi);
|
LOG_TRACE(logAi);
|
||||||
if(h->visitedTown)
|
if(h->getVisitedTown())
|
||||||
townVisitsThisWeek[HeroPtr(h)].insert(h->visitedTown);
|
townVisitsThisWeek[HeroPtr(h)].insert(h->getVisitedTown());
|
||||||
NET_EVENT_HANDLER;
|
NET_EVENT_HANDLER;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1073,12 +1073,12 @@ void VCAI::performObjectInteraction(const CGObjectInstance * obj, HeroPtr h)
|
|||||||
{
|
{
|
||||||
case Obj::TOWN:
|
case Obj::TOWN:
|
||||||
moveCreaturesToHero(dynamic_cast<const CGTownInstance *>(obj));
|
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->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);
|
cb->buyArtifact(h.get(), ArtifactID::SPELLBOOK);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1089,9 +1089,9 @@ void VCAI::performObjectInteraction(const CGObjectInstance * obj, HeroPtr h)
|
|||||||
|
|
||||||
void VCAI::moveCreaturesToHero(const CGTownInstance * t)
|
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
|
auto visitTownIfAny = [this](HeroPtr h) -> bool
|
||||||
{
|
{
|
||||||
if (h->visitedTown)
|
if (h->getVisitedTown())
|
||||||
{
|
{
|
||||||
townVisitsThisWeek[h].insert(h->visitedTown);
|
townVisitsThisWeek[h].insert(h->getVisitedTown());
|
||||||
buildArmyIn(h->visitedTown);
|
buildArmyIn(h->getVisitedTown());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -1434,7 +1434,7 @@ void VCAI::wander(HeroPtr h)
|
|||||||
std::vector<const CGTownInstance *> townsNotReachable;
|
std::vector<const CGTownInstance *> townsNotReachable;
|
||||||
for(const CGTownInstance * t : cb->getTownsInfo())
|
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))
|
if(isAccessibleForHero(t->visitablePos(), h))
|
||||||
townsReachable.push_back(t);
|
townsReachable.push_back(t);
|
||||||
@ -2251,7 +2251,7 @@ void VCAI::tryRealize(Goals::AbstractGoal & g)
|
|||||||
const CGTownInstance * VCAI::findTownWithTavern() const
|
const CGTownInstance * VCAI::findTownWithTavern() const
|
||||||
{
|
{
|
||||||
for(const CGTownInstance * t : cb->getTownsInfo())
|
for(const CGTownInstance * t : cb->getTownsInfo())
|
||||||
if(t->hasBuilt(BuildingID::TAVERN) && !t->visitingHero)
|
if(t->hasBuilt(BuildingID::TAVERN) && !t->getVisitingHero())
|
||||||
return t;
|
return t;
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@ -2455,7 +2455,7 @@ void VCAI::performTypicalActions()
|
|||||||
|
|
||||||
void VCAI::buildArmyIn(const CGTownInstance * t)
|
void VCAI::buildArmyIn(const CGTownInstance * t)
|
||||||
{
|
{
|
||||||
makePossibleUpgrades(t->visitingHero);
|
makePossibleUpgrades(t->getVisitingHero());
|
||||||
makePossibleUpgrades(t);
|
makePossibleUpgrades(t);
|
||||||
recruitCreatures(t, t->getUpperArmy());
|
recruitCreatures(t, t->getUpperArmy());
|
||||||
moveCreaturesToHero(t);
|
moveCreaturesToHero(t);
|
||||||
|
@ -273,7 +273,7 @@ void CCallback::spellResearch( const CGTownInstance *town, SpellID spellAtSlot,
|
|||||||
|
|
||||||
void CCallback::swapGarrisonHero( const CGTownInstance *town )
|
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);
|
GarrisonHeroSwap pack(town->id);
|
||||||
sendRequest(pack);
|
sendRequest(pack);
|
||||||
|
@ -118,18 +118,6 @@
|
|||||||
|
|
||||||
std::shared_ptr<BattleInterface> CPlayerInterface::battleInt;
|
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):
|
CPlayerInterface::CPlayerInterface(PlayerColor Player):
|
||||||
localState(std::make_unique<PlayerLocalState>(*this)),
|
localState(std::make_unique<PlayerLocalState>(*this)),
|
||||||
movementController(std::make_unique<HeroMovementController>()),
|
movementController(std::make_unique<HeroMovementController>()),
|
||||||
@ -542,18 +530,18 @@ void CPlayerInterface::heroInGarrisonChange(const CGTownInstance *town)
|
|||||||
{
|
{
|
||||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
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
|
// 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))
|
if(town->getGarrisonHero()->tempOwner == playerID && vstd::contains(localState->getWanderingHeroes(), town->getGarrisonHero()))
|
||||||
localState->removeWanderingHero(town->garrisonHero);
|
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
|
// 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))
|
if(town->getVisitingHero()->tempOwner == playerID && !vstd::contains(localState->getWanderingHeroes(), town->getVisitingHero()))
|
||||||
localState->addWanderingHero(town->visitingHero);
|
localState->addWanderingHero(town->getVisitingHero());
|
||||||
}
|
}
|
||||||
adventureInt->onHeroChanged(nullptr);
|
adventureInt->onHeroChanged(nullptr);
|
||||||
adventureInt->onTownChanged(town);
|
adventureInt->onTownChanged(town);
|
||||||
@ -611,8 +599,8 @@ void CPlayerInterface::garrisonsChanged(std::vector<const CArmedInstance *> objs
|
|||||||
localState->verifyPath(hero);
|
localState->verifyPath(hero);
|
||||||
|
|
||||||
adventureInt->onHeroChanged(hero);
|
adventureInt->onHeroChanged(hero);
|
||||||
if(hero->inTownGarrison && hero->visitedTown != town)
|
if(hero->isGarrisoned() && hero->getVisitedTown() != town)
|
||||||
adventureInt->onTownChanged(hero->visitedTown);
|
adventureInt->onTownChanged(hero->getVisitedTown());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1363,7 +1351,7 @@ void CPlayerInterface::initializeHeroTownList()
|
|||||||
{
|
{
|
||||||
for(auto & hero : cb->getHeroesInfo())
|
for(auto & hero : cb->getHeroesInfo())
|
||||||
{
|
{
|
||||||
if(!hero->inTownGarrison)
|
if(!hero->isGarrisoned())
|
||||||
localState->addWanderingHero(hero);
|
localState->addWanderingHero(hero);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -703,7 +703,7 @@ void ApplyClientNetPackVisitor::visitCommanderLevelUp(CommanderLevelUp & pack)
|
|||||||
{
|
{
|
||||||
const CGHeroInstance * hero = cl.getHero(pack.heroId);
|
const CGHeroInstance * hero = cl.getHero(pack.heroId);
|
||||||
assert(hero);
|
assert(hero);
|
||||||
const CCommanderInstance * commander = hero->commander;
|
const auto & commander = hero->getCommander();
|
||||||
assert(commander);
|
assert(commander);
|
||||||
assert(commander->armyObj); //is it possible for Commander to exist beyond armed instance?
|
assert(commander->armyObj); //is it possible for Commander to exist beyond armed instance?
|
||||||
callOnlyThatInterface(cl, pack.player, &CGameInterface::commanderGotLevel, commander, pack.skills, pack.queryID);
|
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);
|
const auto * hero = dynamic_cast<const CGHeroInstance *>(object);
|
||||||
|
|
||||||
if(hero->inTownGarrison)
|
if(hero->isGarrisoned())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if(hero->boat)
|
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
|
const bool isHeroOnMap = owner->upperArmy() // Hero is not a visitor and not a garrison defender
|
||||||
&& owner->upperArmy()->ID == Obj::HERO
|
&& owner->upperArmy()->ID == Obj::HERO
|
||||||
&& (!owner->lowerArmy() || owner->lowerArmy()->ID == Obj::HERO) // one hero or we are in the Heroes exchange window
|
&& (!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)
|
if(isHeroOnMap)
|
||||||
{
|
{
|
||||||
|
@ -595,16 +595,16 @@ HeroSlots::HeroSlots(const CGTownInstance * Town, Point garrPos, Point visitPos,
|
|||||||
garr(Garrison)
|
garr(Garrison)
|
||||||
{
|
{
|
||||||
OBJECT_CONSTRUCTION;
|
OBJECT_CONSTRUCTION;
|
||||||
garrisonedHero = std::make_shared<CHeroGSlot>(garrPos.x, garrPos.y, 0, town->garrisonHero, 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->visitingHero, this);
|
visitingHero = std::make_shared<CHeroGSlot>(visitPos.x, visitPos.y, 1, town->getVisitingHero(), this);
|
||||||
}
|
}
|
||||||
|
|
||||||
HeroSlots::~HeroSlots() = default;
|
HeroSlots::~HeroSlots() = default;
|
||||||
|
|
||||||
void HeroSlots::update()
|
void HeroSlots::update()
|
||||||
{
|
{
|
||||||
garrisonedHero->set(town->garrisonHero);
|
garrisonedHero->set(town->getGarrisonHero());
|
||||||
visitingHero->set(town->visitingHero);
|
visitingHero->set(town->getVisitingHero());
|
||||||
}
|
}
|
||||||
|
|
||||||
void HeroSlots::swapArmies()
|
void HeroSlots::swapArmies()
|
||||||
@ -612,9 +612,9 @@ void HeroSlots::swapArmies()
|
|||||||
bool allow = true;
|
bool allow = true;
|
||||||
|
|
||||||
//moving hero out of town - check if it is allowed
|
//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.
|
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)));
|
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);
|
GAME->interface()->showInfoDialog(text, std::vector<std::shared_ptr<CComponent>>(), soundBase::sound_todo);
|
||||||
allow = false;
|
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.
|
//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);
|
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);
|
GAME->interface()->showInfoDialog(LIBRARY->generaltexth->allTexts[275], std::vector<std::shared_ptr<CComponent>>(), soundBase::sound_todo);
|
||||||
allow = false;
|
allow = false;
|
||||||
@ -809,10 +809,10 @@ void CCastleBuildings::removeBuilding(BuildingID building)
|
|||||||
|
|
||||||
const CGHeroInstance * CCastleBuildings::getHero()
|
const CGHeroInstance * CCastleBuildings::getHero()
|
||||||
{
|
{
|
||||||
if(town->visitingHero)
|
if(town->getVisitingHero())
|
||||||
return town->visitingHero;
|
return town->getVisitingHero();
|
||||||
else
|
else
|
||||||
return town->garrisonHero;
|
return town->getGarrisonHero();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CCastleBuildings::buildingClicked(BuildingID building)
|
void CCastleBuildings::buildingClicked(BuildingID building)
|
||||||
@ -983,7 +983,7 @@ bool CCastleBuildings::buildingTryActivateCustomUI(BuildingID buildingToTest, Bu
|
|||||||
|
|
||||||
void CCastleBuildings::enterRewardable(BuildingID building)
|
void CCastleBuildings::enterRewardable(BuildingID building)
|
||||||
{
|
{
|
||||||
if (town->visitingHero == nullptr)
|
if (town->getVisitingHero() == nullptr)
|
||||||
{
|
{
|
||||||
MetaString message;
|
MetaString message;
|
||||||
message.appendTextID("core.genrltxt.273"); // only visiting heroes may visit %s
|
message.appendTextID("core.genrltxt.273"); // only visiting heroes may visit %s
|
||||||
@ -993,7 +993,7 @@ void CCastleBuildings::enterRewardable(BuildingID building)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (town->rewardableBuildings.at(building)->wasVisited(town->visitingHero))
|
if (town->rewardableBuildings.at(building)->wasVisited(town->getVisitingHero()))
|
||||||
enterBuilding(building);
|
enterBuilding(building);
|
||||||
else
|
else
|
||||||
GAME->interface()->cb->visitTownBuilding(town, building);
|
GAME->interface()->cb->visitTownBuilding(town, building);
|
||||||
@ -1002,7 +1002,7 @@ void CCastleBuildings::enterRewardable(BuildingID building)
|
|||||||
|
|
||||||
void CCastleBuildings::enterBlacksmith(BuildingID building, ArtifactID artifactID)
|
void CCastleBuildings::enterBlacksmith(BuildingID building, ArtifactID artifactID)
|
||||||
{
|
{
|
||||||
const CGHeroInstance *hero = town->visitingHero;
|
const CGHeroInstance *hero = town->getVisitingHero();
|
||||||
if(!hero)
|
if(!hero)
|
||||||
{
|
{
|
||||||
GAME->interface()->showInfoDialog(boost::str(boost::format(LIBRARY->generaltexth->allTexts[273]) % town->getTown()->buildings.find(building)->second->getNameTranslated()));
|
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)
|
void CCastleBuildings::enterCastleGate(BuildingID building)
|
||||||
{
|
{
|
||||||
if (!town->visitingHero)
|
if (!town->getVisitingHero())
|
||||||
{
|
{
|
||||||
GAME->interface()->showInfoDialog(LIBRARY->generaltexth->allTexts[126]);
|
GAME->interface()->showInfoDialog(LIBRARY->generaltexth->allTexts[126]);
|
||||||
return;//only visiting hero can use castle gates
|
return;//only visiting hero can use castle gates
|
||||||
@ -1051,7 +1051,7 @@ void CCastleBuildings::enterCastleGate(BuildingID building)
|
|||||||
for(auto & Town : Towns)
|
for(auto & Town : Towns)
|
||||||
{
|
{
|
||||||
const CGTownInstance *t = Town;
|
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->getFactionID() == town->getFactionID() && //the town of the same faction
|
||||||
t->hasBuilt(BuildingSubID::CASTLE_GATE)) //and the town has a castle gate
|
t->hasBuilt(BuildingSubID::CASTLE_GATE)) //and the town has a castle gate
|
||||||
{
|
{
|
||||||
@ -1169,7 +1169,7 @@ void CCastleBuildings::enterMagesGuild()
|
|||||||
|
|
||||||
void CCastleBuildings::enterTownHall()
|
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
|
!town->hasBuilt(BuildingID::GRAIL)) //hero has grail, but town does not have it
|
||||||
{
|
{
|
||||||
if(!vstd::contains(town->forbiddenBuildings, BuildingID::GRAIL))
|
if(!vstd::contains(town->forbiddenBuildings, BuildingID::GRAIL))
|
||||||
@ -1427,7 +1427,7 @@ CCastleInterface::CCastleInterface(const CGTownInstance * Town, const CGTownInst
|
|||||||
center();
|
center();
|
||||||
updateShadow();
|
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);
|
garr->setRedrawParent(true);
|
||||||
|
|
||||||
heroes = std::make_shared<HeroSlots>(town, Point(241, 387), Point(241, 483), garr, true);
|
heroes = std::make_shared<HeroSlots>(town, Point(241, 387), Point(241, 483), garr, true);
|
||||||
@ -1476,7 +1476,7 @@ CCastleInterface::~CCastleInterface()
|
|||||||
void CCastleInterface::updateGarrisons()
|
void CCastleInterface::updateGarrisons()
|
||||||
{
|
{
|
||||||
garr->setArmy(town->getUpperArmy(), EGarrisonType::UPPER);
|
garr->setArmy(town->getUpperArmy(), EGarrisonType::UPPER);
|
||||||
garr->setArmy(town->visitingHero, EGarrisonType::LOWER);
|
garr->setArmy(town->getVisitingHero(), EGarrisonType::LOWER);
|
||||||
garr->recreateSlots();
|
garr->recreateSlots();
|
||||||
heroes->update();
|
heroes->update();
|
||||||
|
|
||||||
@ -1485,15 +1485,15 @@ void CCastleInterface::updateGarrisons()
|
|||||||
|
|
||||||
bool CCastleInterface::holdsGarrison(const CArmedInstance * army)
|
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()
|
void CCastleInterface::close()
|
||||||
{
|
{
|
||||||
if(town->tempOwner == GAME->interface()->playerID) //we may have opened window for an allied town
|
if(town->tempOwner == GAME->interface()->playerID) //we may have opened window for an allied town
|
||||||
{
|
{
|
||||||
if(town->visitingHero && town->visitingHero->tempOwner == GAME->interface()->playerID)
|
if(town->getVisitingHero() && town->getVisitingHero()->tempOwner == GAME->interface()->playerID)
|
||||||
GAME->interface()->localState->setSelection(town->visitingHero);
|
GAME->interface()->localState->setSelection(town->getVisitingHero());
|
||||||
else
|
else
|
||||||
GAME->interface()->localState->setSelection(town);
|
GAME->interface()->localState->setSelection(town);
|
||||||
}
|
}
|
||||||
@ -1503,9 +1503,9 @@ void CCastleInterface::close()
|
|||||||
void CCastleInterface::castleTeleport(int where)
|
void CCastleInterface::castleTeleport(int where)
|
||||||
{
|
{
|
||||||
const CGTownInstance * dest = GAME->interface()->cb->getTown(ObjectInstanceID(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()->localState->setSelection(town->getVisitingHero());//according to assert(ho == adventureInt->selection) in the eraseCurrentPathOf
|
||||||
GAME->interface()->cb->teleportHero(town->visitingHero, dest);
|
GAME->interface()->cb->teleportHero(town->getVisitingHero(), dest);
|
||||||
GAME->interface()->localState->erasePath(town->visitingHero);
|
GAME->interface()->localState->erasePath(town->getVisitingHero());
|
||||||
}
|
}
|
||||||
|
|
||||||
void CCastleInterface::townChange()
|
void CCastleInterface::townChange()
|
||||||
@ -1605,22 +1605,22 @@ void CCastleInterface::keyPressed(EShortcut key)
|
|||||||
case EShortcut::TOWN_OPEN_THIEVES_GUILD:
|
case EShortcut::TOWN_OPEN_THIEVES_GUILD:
|
||||||
break;
|
break;
|
||||||
case EShortcut::TOWN_OPEN_HERO_EXCHANGE:
|
case EShortcut::TOWN_OPEN_HERO_EXCHANGE:
|
||||||
if (town->visitingHero && town->garrisonHero)
|
if (town->getVisitingHero() && town->getGarrisonHero())
|
||||||
GAME->interface()->showHeroExchange(town->visitingHero->id, town->garrisonHero->id);
|
GAME->interface()->showHeroExchange(town->getVisitingHero()->id, town->getGarrisonHero()->id);
|
||||||
break;
|
break;
|
||||||
case EShortcut::TOWN_OPEN_HERO:
|
case EShortcut::TOWN_OPEN_HERO:
|
||||||
if (town->visitingHero)
|
if (town->getVisitingHero())
|
||||||
GAME->interface()->openHeroWindow(town->visitingHero);
|
GAME->interface()->openHeroWindow(town->getVisitingHero());
|
||||||
else if (town->garrisonHero)
|
else if (town->getGarrisonHero())
|
||||||
GAME->interface()->openHeroWindow(town->garrisonHero);
|
GAME->interface()->openHeroWindow(town->getGarrisonHero());
|
||||||
break;
|
break;
|
||||||
case EShortcut::TOWN_OPEN_VISITING_HERO:
|
case EShortcut::TOWN_OPEN_VISITING_HERO:
|
||||||
if (town->visitingHero)
|
if (town->getVisitingHero())
|
||||||
GAME->interface()->openHeroWindow(town->visitingHero);
|
GAME->interface()->openHeroWindow(town->getVisitingHero());
|
||||||
break;
|
break;
|
||||||
case EShortcut::TOWN_OPEN_GARRISONED_HERO:
|
case EShortcut::TOWN_OPEN_GARRISONED_HERO:
|
||||||
if (town->garrisonHero)
|
if (town->getGarrisonHero())
|
||||||
GAME->interface()->openHeroWindow(town->garrisonHero);
|
GAME->interface()->openHeroWindow(town->getGarrisonHero());
|
||||||
break;
|
break;
|
||||||
case EShortcut::TOWN_SWAP_ARMIES:
|
case EShortcut::TOWN_SWAP_ARMIES:
|
||||||
heroes->swapArmies();
|
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(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));
|
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 = 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")));
|
commanderButton->setOverlay(std::make_shared<CPicture>(ImagePath::builtin("heroWindow/commanderButtonIcon")));
|
||||||
@ -328,7 +328,7 @@ void CHeroWindow::commanderWindow()
|
|||||||
|
|
||||||
if(pickedArtInst)
|
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!
|
if(vstd::contains(ArtifactUtils::commanderSlots(), freeSlot)) // We don't want to put it in commander's backpack!
|
||||||
{
|
{
|
||||||
ArtifactLocation dst(curHero->id, freeSlot);
|
ArtifactLocation dst(curHero->id, freeSlot);
|
||||||
@ -338,7 +338,7 @@ void CHeroWindow::commanderWindow()
|
|||||||
}
|
}
|
||||||
else
|
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);
|
hall = std::make_shared<CTownInfo>( 69, 31, town, true);
|
||||||
fort = std::make_shared<CTownInfo>(111, 31, town, false);
|
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);
|
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)];
|
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->selectSlot(nullptr);
|
||||||
garr->setArmy(town->getUpperArmy(), EGarrisonType::UPPER);
|
garr->setArmy(town->getUpperArmy(), EGarrisonType::UPPER);
|
||||||
garr->setArmy(town->visitingHero, EGarrisonType::LOWER);
|
garr->setArmy(town->getVisitingHero(), EGarrisonType::LOWER);
|
||||||
garr->recreateSlots();
|
garr->recreateSlots();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CTownItem::holdsGarrison(const CArmedInstance * army)
|
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()
|
void CTownItem::update()
|
||||||
|
@ -517,7 +517,7 @@ CTavernWindow::CTavernWindow(const CGObjectInstance * TavernObj, const std::func
|
|||||||
recruit->addHoverText(EButtonState::NORMAL, message.toString());
|
recruit->addHoverText(EButtonState::NORMAL, message.toString());
|
||||||
recruit->block(true);
|
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->addHoverText(EButtonState::NORMAL, LIBRARY->generaltexth->tavernInfo[2]); //Cannot recruit. You already have a Hero in this town.
|
||||||
recruit->block(true);
|
recruit->block(true);
|
||||||
|
@ -499,7 +499,7 @@ bool CCreatureSet::contains(const CStackInstance *stack) const
|
|||||||
SlotID CCreatureSet::findStack(const CStackInstance *stack) const
|
SlotID CCreatureSet::findStack(const CStackInstance *stack) const
|
||||||
{
|
{
|
||||||
const auto * h = dynamic_cast<const CGHeroInstance *>(this);
|
const auto * h = dynamic_cast<const CGHeroInstance *>(this);
|
||||||
if (h && h->commander == stack)
|
if (h && h->getCommander() == stack)
|
||||||
return SlotID::COMMANDER_SLOT_PLACEHOLDER;
|
return SlotID::COMMANDER_SLOT_PLACEHOLDER;
|
||||||
|
|
||||||
if(!stack)
|
if(!stack)
|
||||||
|
@ -721,7 +721,7 @@ int CGameInfoCallback::getHeroCount( PlayerColor player, bool includeGarrisoned
|
|||||||
return static_cast<int>(p->getHeroes().size());
|
return static_cast<int>(p->getHeroes().size());
|
||||||
else
|
else
|
||||||
for(const auto & elem : p->getHeroes())
|
for(const auto & elem : p->getHeroes())
|
||||||
if(!elem->inTownGarrison)
|
if(!elem->isGarrisoned())
|
||||||
ret++;
|
ret++;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -792,7 +792,7 @@ std::vector < const CGHeroInstance *> CPlayerSpecificInfoCallback::getHeroesInfo
|
|||||||
|
|
||||||
int CPlayerSpecificInfoCallback::getHeroSerial(const CGHeroInstance * hero, bool includeGarrisoned) const
|
int CPlayerSpecificInfoCallback::getHeroSerial(const CGHeroInstance * hero, bool includeGarrisoned) const
|
||||||
{
|
{
|
||||||
if (hero->inTownGarrison && !includeGarrisoned)
|
if (hero->isGarrisoned() && !includeGarrisoned)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
size_t index = 0;
|
size_t index = 0;
|
||||||
@ -800,7 +800,7 @@ int CPlayerSpecificInfoCallback::getHeroSerial(const CGHeroInstance * hero, bool
|
|||||||
|
|
||||||
for (auto & possibleHero : heroes)
|
for (auto & possibleHero : heroes)
|
||||||
{
|
{
|
||||||
if (includeGarrisoned || !(possibleHero)->inTownGarrison)
|
if (includeGarrisoned || !(possibleHero)->isGarrisoned())
|
||||||
index++;
|
index++;
|
||||||
|
|
||||||
if (possibleHero == hero)
|
if (possibleHero == hero)
|
||||||
@ -853,7 +853,7 @@ const CGHeroInstance* CPlayerSpecificInfoCallback::getHeroBySerial(int serialId,
|
|||||||
if (!includeGarrisoned)
|
if (!includeGarrisoned)
|
||||||
{
|
{
|
||||||
for(ui32 i = 0; i < p->getHeroes().size() && static_cast<int>(i) <= serialId; i++)
|
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++;
|
serialId++;
|
||||||
}
|
}
|
||||||
ERROR_RET_VAL_IF(serialId < 0 || serialId >= p->getHeroes().size(), "No player info", nullptr);
|
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);
|
const auto * hero = dynamic_cast<const CGHeroInstance *>(army);
|
||||||
assert(hero);
|
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)
|
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.has_value())
|
||||||
{
|
{
|
||||||
if(loc.creature.value() == SlotID::COMMANDER_SLOT_PLACEHOLDER)
|
if(loc.creature.value() == SlotID::COMMANDER_SLOT_PLACEHOLDER)
|
||||||
return hero->commander;
|
return hero->getCommander();
|
||||||
else
|
else
|
||||||
return hero->getStackPtr(loc.creature.value());
|
return hero->getStackPtr(loc.creature.value());
|
||||||
}
|
}
|
||||||
|
@ -351,9 +351,9 @@ BattleInfo * BattleInfo::setupBattle(const int3 & tile, TerrainId terrain, const
|
|||||||
//adding commanders
|
//adding commanders
|
||||||
for(BattleSide i : {BattleSide::ATTACKER, BattleSide::DEFENDER})
|
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()))
|
if (t->visitableAt(h->visitablePos()))
|
||||||
{
|
{
|
||||||
assert(t->visitingHero == nullptr);
|
assert(t->getVisitingHero() == nullptr);
|
||||||
t->setVisitingHero(h);
|
t->setVisitingHero(h);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1000,9 +1000,9 @@ void CGameState::initVisitingAndGarrisonedHeroes()
|
|||||||
}
|
}
|
||||||
for (auto hero : map->heroesOnMap)
|
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);
|
auto hero = dynamic_cast<const CGHeroInstance *>(stack.armyObj);
|
||||||
hero->fillUpgradeInfo(ret, stack);
|
hero->fillUpgradeInfo(ret, stack);
|
||||||
|
|
||||||
if (hero->visitedTown)
|
if (hero->getVisitedTown())
|
||||||
{
|
{
|
||||||
hero->visitedTown->fillUpgradeInfo(ret, stack);
|
hero->getVisitedTown()->fillUpgradeInfo(ret, stack);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1382,8 +1382,8 @@ bool CGameState::checkForVictory(const PlayerColor & player, const EventConditio
|
|||||||
case EventCondition::TRANSPORT:
|
case EventCondition::TRANSPORT:
|
||||||
{
|
{
|
||||||
const auto * t = getTown(condition.objectID);
|
const auto * t = getTown(condition.objectID);
|
||||||
bool garrisonedWon = t->garrisonHero && t->garrisonHero->getOwner() == player && t->garrisonHero->hasArt(condition.objectType.as<ArtifactID>());
|
bool garrisonedWon = t->getGarrisonHero() && t->getGarrisonHero()->getOwner() == player && t->getGarrisonHero()->hasArt(condition.objectType.as<ArtifactID>());
|
||||||
bool visitingWon = t->visitingHero && t->visitingHero->getOwner() == player && t->visitingHero->hasArt(condition.objectType.as<ArtifactID>());
|
bool visitingWon = t->getVisitingHero() && t->getVisitingHero()->getOwner() == player && t->getVisitingHero()->hasArt(condition.objectType.as<ArtifactID>());
|
||||||
|
|
||||||
return garrisonedWon || visitingWon;
|
return garrisonedWon || visitingWon;
|
||||||
}
|
}
|
||||||
|
@ -244,7 +244,7 @@ si64 Statistic::getArmyStrength(const PlayerState * ps, bool withTownGarrison)
|
|||||||
|
|
||||||
for(auto h : ps->getHeroes())
|
for(auto h : ps->getHeroes())
|
||||||
{
|
{
|
||||||
if(!h->inTownGarrison || withTownGarrison) //original h3 behavior
|
if(!h->isGarrisoned() || withTownGarrison) //original h3 behavior
|
||||||
str += h->getArmyStrength();
|
str += h->getArmyStrength();
|
||||||
}
|
}
|
||||||
return str;
|
return str;
|
||||||
|
@ -183,7 +183,7 @@ void InfoAboutTown::initFromTown(const CGTownInstance *t, bool detailed)
|
|||||||
details->goldIncome = income[EGameResID::GOLD];
|
details->goldIncome = income[EGameResID::GOLD];
|
||||||
details->customRes = t->hasBuilt(BuildingID::RESOURCE_SILO);
|
details->customRes = t->hasBuilt(BuildingID::RESOURCE_SILO);
|
||||||
details->hallLevel = t->hallLevel();
|
details->hallLevel = t->hallLevel();
|
||||||
details->garrisonedHero = t->garrisonHero;
|
details->garrisonedHero = t->getGarrisonHero();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -308,6 +308,47 @@ void CGHeroInstance::setHeroType(HeroTypeID heroType)
|
|||||||
subID = 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)
|
void CGHeroInstance::initObj(vstd::RNG & rand)
|
||||||
{
|
{
|
||||||
if (ID == Obj::HERO)
|
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())
|
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->setArmyObj (castToArmyObj()); //TODO: separate function for setting commanders
|
||||||
commander->giveStackExp (exp); //after our exp is set
|
commander->giveStackExp (exp); //after our exp is set
|
||||||
}
|
}
|
||||||
@ -504,10 +545,7 @@ void CGHeroInstance::initArmy(vstd::RNG & rand, IArmyDescriptor * dst)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CGHeroInstance::~CGHeroInstance()
|
CGHeroInstance::~CGHeroInstance() = default;
|
||||||
{
|
|
||||||
commander.dellNull();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CGHeroInstance::needsLastStack() const
|
bool CGHeroInstance::needsLastStack() const
|
||||||
{
|
{
|
||||||
@ -527,8 +565,8 @@ void CGHeroInstance::onHeroVisit(const CGHeroInstance * h) const
|
|||||||
}
|
}
|
||||||
else //battle
|
else //battle
|
||||||
{
|
{
|
||||||
if(visitedTown) //we're in town
|
if(getVisitedTown()) //we're in town
|
||||||
visitedTown->onHeroVisit(h); //town will handle attacking
|
getVisitedTown()->onHeroVisit(h); //town will handle attacking
|
||||||
else
|
else
|
||||||
cb->startBattle(h, this);
|
cb->startBattle(h, this);
|
||||||
}
|
}
|
||||||
@ -1060,7 +1098,7 @@ si32 CGHeroInstance::manaRegain() const
|
|||||||
|
|
||||||
si32 CGHeroInstance::getManaNewTurn() 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
|
//if hero starts turn in town with mage guild - restore all mana
|
||||||
return std::max(mana, manaLimit());
|
return std::max(mana, manaLimit());
|
||||||
@ -1280,30 +1318,30 @@ void CGHeroInstance::boatDeserializationFix()
|
|||||||
|
|
||||||
CBonusSystemNode * CGHeroInstance::whereShouldBeAttachedOnSiege(const bool isBattleOutsideTown) const
|
CBonusSystemNode * CGHeroInstance::whereShouldBeAttachedOnSiege(const bool isBattleOutsideTown) const
|
||||||
{
|
{
|
||||||
if(!visitedTown)
|
if(!getVisitedTown())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
return isBattleOutsideTown ? (CBonusSystemNode *)(& visitedTown->townAndVis)
|
return isBattleOutsideTown ? (CBonusSystemNode *)(& getVisitedTown()->townAndVis)
|
||||||
: (CBonusSystemNode *)(visitedTown.get());
|
: (CBonusSystemNode *)(getVisitedTown());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CBonusSystemNode * CGHeroInstance::whereShouldBeAttachedOnSiege(CGameState * gs)
|
CBonusSystemNode * CGHeroInstance::whereShouldBeAttachedOnSiege(CGameState * gs)
|
||||||
{
|
{
|
||||||
if(visitedTown)
|
if(getVisitedTown())
|
||||||
return whereShouldBeAttachedOnSiege(visitedTown->isBattleOutsideTown(this));
|
return whereShouldBeAttachedOnSiege(getVisitedTown()->isBattleOutsideTown(this));
|
||||||
|
|
||||||
return &CArmedInstance::whereShouldBeAttached(gs);
|
return &CArmedInstance::whereShouldBeAttached(gs);
|
||||||
}
|
}
|
||||||
|
|
||||||
CBonusSystemNode & CGHeroInstance::whereShouldBeAttached(CGameState * gs)
|
CBonusSystemNode & CGHeroInstance::whereShouldBeAttached(CGameState * gs)
|
||||||
{
|
{
|
||||||
if(visitedTown)
|
if(getVisitedTown())
|
||||||
{
|
{
|
||||||
if(inTownGarrison)
|
if(isGarrisoned())
|
||||||
return *visitedTown;
|
return *getVisitedTown();
|
||||||
else
|
else
|
||||||
return visitedTown->townAndVis;
|
return getVisitedTown()->townAndVis;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return CArmedInstance::whereShouldBeAttached(gs);
|
return CArmedInstance::whereShouldBeAttached(gs);
|
||||||
|
@ -17,7 +17,6 @@
|
|||||||
#include "../bonuses/BonusCache.h"
|
#include "../bonuses/BonusCache.h"
|
||||||
#include "../entities/hero/EHeroGender.h"
|
#include "../entities/hero/EHeroGender.h"
|
||||||
#include "../CArtHandler.h" // For CArtifactSet
|
#include "../CArtHandler.h" // For CArtifactSet
|
||||||
#include "../ConstTransitivePtr.h"
|
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_BEGIN
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
@ -66,12 +65,14 @@ private:
|
|||||||
MagicSchoolMasteryCache magicSchoolMastery;
|
MagicSchoolMasteryCache magicSchoolMastery;
|
||||||
BonusValueCache manaPerKnowledgeCached;
|
BonusValueCache manaPerKnowledgeCached;
|
||||||
std::unique_ptr<TurnInfoCache> turnInfoCache;
|
std::unique_ptr<TurnInfoCache> turnInfoCache;
|
||||||
|
std::unique_ptr<CCommanderInstance> commander;
|
||||||
|
|
||||||
std::set<SpellID> spells; //known spells (spell IDs)
|
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
|
ui32 movement; //remaining movement points
|
||||||
|
bool inTownGarrison; // if hero is in town garrison
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
//format: 123
|
//format: 123
|
||||||
// 8 4
|
// 8 4
|
||||||
@ -93,9 +94,6 @@ public:
|
|||||||
std::string nameCustomTextId;
|
std::string nameCustomTextId;
|
||||||
std::string biographyCustomTextId;
|
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
|
const CGBoat * boat = nullptr; //set to CGBoat when sailing
|
||||||
|
|
||||||
static constexpr si32 UNINITIALIZED_MANA = -1;
|
static constexpr si32 UNINITIALIZED_MANA = -1;
|
||||||
@ -103,8 +101,6 @@ public:
|
|||||||
static constexpr auto UNINITIALIZED_EXPERIENCE = std::numeric_limits<TExpType>::max();
|
static constexpr auto UNINITIALIZED_EXPERIENCE = std::numeric_limits<TExpType>::max();
|
||||||
static const ui32 NO_PATROLLING;
|
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;
|
std::set<ObjectInstanceID> visitedObjects;
|
||||||
|
|
||||||
struct DLL_LINKAGE Patrol
|
struct DLL_LINKAGE Patrol
|
||||||
@ -252,6 +248,14 @@ public:
|
|||||||
HeroTypeID getHeroTypeID() const;
|
HeroTypeID getHeroTypeID() const;
|
||||||
void setHeroType(HeroTypeID type);
|
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 initObj(vstd::RNG & rand) override;
|
||||||
void initHero(vstd::RNG & rand);
|
void initHero(vstd::RNG & rand);
|
||||||
void initHero(vstd::RNG & rand, const HeroTypeID & SUBID);
|
void initHero(vstd::RNG & rand, const HeroTypeID & SUBID);
|
||||||
|
@ -59,13 +59,13 @@ void CGTownInstance::setPropertyDer(ObjProperty what, ObjPropertyID identifier)
|
|||||||
switch (what)
|
switch (what)
|
||||||
{
|
{
|
||||||
case ObjProperty::STRUCTURE_ADD_VISITING_HERO:
|
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;
|
break;
|
||||||
case ObjProperty::STRUCTURE_CLEAR_VISITORS:
|
case ObjProperty::STRUCTURE_CLEAR_VISITORS:
|
||||||
rewardableBuildings.at(identifier.getNum())->setProperty(ObjProperty::STRUCTURE_CLEAR_VISITORS, NumericID(0));
|
rewardableBuildings.at(identifier.getNum())->setProperty(ObjProperty::STRUCTURE_CLEAR_VISITORS, NumericID(0));
|
||||||
break;
|
break;
|
||||||
case ObjProperty::STRUCTURE_ADD_GARRISONED_HERO: //add garrisoned hero to visitors
|
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;
|
break;
|
||||||
case ObjProperty::BONUS_VALUE_FIRST:
|
case ObjProperty::BONUS_VALUE_FIRST:
|
||||||
bonusValue.first = identifier.getNum();
|
bonusValue.first = identifier.getNum();
|
||||||
@ -296,7 +296,7 @@ int CGTownInstance::spellsAtLevel(int level, bool checkGuild) const
|
|||||||
|
|
||||||
bool CGTownInstance::needsLastStack() const
|
bool CGTownInstance::needsLastStack() const
|
||||||
{
|
{
|
||||||
return garrisonHero != nullptr;
|
return getGarrisonHero() != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CGTownInstance::setOwner(const PlayerColor & player) const
|
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(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 CArmedInstance * defendingArmy = defendingHero ? (CArmedInstance *)defendingHero : this;
|
||||||
const bool isBattleOutside = isBattleOutsideTown(defendingHero);
|
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)
|
//we have two approaches to merge armies: mergeGarrisonOnSiege() and used in the CGameHandler::garrisonSwap(ObjectInstanceID tid)
|
||||||
auto * nodeSiege = defendingHero->whereShouldBeAttachedOnSiege(isBattleOutside);
|
auto * nodeSiege = defendingHero->whereShouldBeAttachedOnSiege(isBattleOutside);
|
||||||
@ -323,7 +323,7 @@ void CGTownInstance::onHeroVisit(const CGHeroInstance * h) const
|
|||||||
if(nodeSiege == (CBonusSystemNode *)this)
|
if(nodeSiege == (CBonusSystemNode *)this)
|
||||||
cb->swapGarrisonOnSiege(this->id);
|
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));
|
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
|
else
|
||||||
{
|
{
|
||||||
assert(h->visitablePos() == this->visitablePos());
|
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
|
if (commander_recover) // rise commander from dead
|
||||||
{
|
{
|
||||||
SetCommanderProperty scp;
|
SetCommanderProperty scp;
|
||||||
@ -358,8 +358,8 @@ void CGTownInstance::onHeroVisit(const CGHeroInstance * h) const
|
|||||||
{
|
{
|
||||||
InfoWindow iw;
|
InfoWindow iw;
|
||||||
iw.player = h->tempOwner;
|
iw.player = h->tempOwner;
|
||||||
iw.text.appendRawString(h->commander->getName());
|
iw.text.appendRawString(h->getCommander()->getName());
|
||||||
iw.components.emplace_back(ComponentType::CREATURE, h->commander->getId(), h->commander->getCount());
|
iw.components.emplace_back(ComponentType::CREATURE, h->getCommander()->getId(), h->getCommander()->getCount());
|
||||||
cb->showInfoDialog(&iw);
|
cb->showInfoDialog(&iw);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -368,7 +368,7 @@ void CGTownInstance::onHeroVisit(const CGHeroInstance * h) const
|
|||||||
void CGTownInstance::onHeroLeave(const CGHeroInstance * h) const
|
void CGTownInstance::onHeroLeave(const CGHeroInstance * h) const
|
||||||
{
|
{
|
||||||
//FIXME: find out why this issue appears on random maps
|
//FIXME: find out why this issue appears on random maps
|
||||||
if(visitingHero == h)
|
if(getVisitingHero() == h)
|
||||||
{
|
{
|
||||||
cb->stopHeroVisitCastle(this, h);
|
cb->stopHeroVisitCastle(this, h);
|
||||||
logGlobal->trace("%s correctly left town %s", h->getNameTranslated(), getNameTranslated());
|
logGlobal->trace("%s correctly left town %s", h->getNameTranslated(), getNameTranslated());
|
||||||
@ -584,13 +584,13 @@ void CGTownInstance::mergeGarrisonOnSiege() const
|
|||||||
auto getWeakestStackSlot = [&](ui64 powerLimit)
|
auto getWeakestStackSlot = [&](ui64 powerLimit)
|
||||||
{
|
{
|
||||||
std::vector<SlotID> weakSlots;
|
std::vector<SlotID> weakSlots;
|
||||||
auto stacksList = visitingHero->stacks;
|
auto stacksList = getVisitingHero()->stacks;
|
||||||
std::pair<SlotID, CStackInstance *> pair;
|
std::pair<SlotID, CStackInstance *> pair;
|
||||||
while(!stacksList.empty())
|
while(!stacksList.empty())
|
||||||
{
|
{
|
||||||
pair = *vstd::minElementByFun(stacksList, [&](const std::pair<SlotID, CStackInstance *> & elem) { return elem.second->getPower(); });
|
pair = *vstd::minElementByFun(stacksList, [&](const std::pair<SlotID, CStackInstance *> & elem) { return elem.second->getPower(); });
|
||||||
if(powerLimit > pair.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);
|
weakSlots.push_back(pair.first);
|
||||||
stacksList.erase(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)
|
auto pair = *vstd::maxElementByFun(stacks, [&](const std::pair<SlotID, CStackInstance *> & elem)
|
||||||
{
|
{
|
||||||
ui64 power = elem.second->getPower();
|
ui64 power = elem.second->getPower();
|
||||||
auto dst = visitingHero->getSlotFor(elem.second->getCreatureID());
|
auto dst = getVisitingHero()->getSlotFor(elem.second->getCreatureID());
|
||||||
if(dst.validSlot() && visitingHero->hasStackAtSlot(dst))
|
if(dst.validSlot() && getVisitingHero()->hasStackAtSlot(dst))
|
||||||
power += visitingHero->getStack(dst).getPower();
|
power += getVisitingHero()->getStack(dst).getPower();
|
||||||
|
|
||||||
return power;
|
return power;
|
||||||
});
|
});
|
||||||
auto dst = visitingHero->getSlotFor(pair.second->getCreatureID());
|
auto dst = getVisitingHero()->getSlotFor(pair.second->getCreatureID());
|
||||||
if(dst.validSlot())
|
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
|
else
|
||||||
{
|
{
|
||||||
dst = getWeakestStackSlot(static_cast<int>(pair.second->getPower()));
|
dst = getWeakestStackSlot(static_cast<int>(pair.second->getPower()));
|
||||||
if(dst.validSlot())
|
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
|
//Hero is already handled by CGameState::attachArmedObjects
|
||||||
|
|
||||||
// if(visitingHero)
|
// if(getVisitingHero())
|
||||||
// visitingHero->attachTo(&townAndVis);
|
// getVisitingHero()->attachTo(&townAndVis);
|
||||||
// if(garrisonHero)
|
// if(getGarrisonHero())
|
||||||
// garrisonHero->attachTo(this);
|
// getGarrisonHero()->attachTo(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CGTownInstance::updateMoraleBonusFromArmy()
|
void CGTownInstance::updateMoraleBonusFromArmy()
|
||||||
@ -737,7 +737,7 @@ void CGTownInstance::updateMoraleBonusFromArmy()
|
|||||||
addNewBonus(b);
|
addNewBonus(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (garrisonHero)
|
if (getGarrisonHero())
|
||||||
{
|
{
|
||||||
b->val = 0;
|
b->val = 0;
|
||||||
nodeHasChanged();
|
nodeHasChanged();
|
||||||
@ -786,7 +786,7 @@ void CGTownInstance::recreateBuildingsBonuses()
|
|||||||
|
|
||||||
void CGTownInstance::setVisitingHero(CGHeroInstance *h)
|
void CGTownInstance::setVisitingHero(CGHeroInstance *h)
|
||||||
{
|
{
|
||||||
if(visitingHero.get() == h)
|
if(getVisitingHero() == h)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if(h)
|
if(h)
|
||||||
@ -795,23 +795,23 @@ void CGTownInstance::setVisitingHero(CGHeroInstance *h)
|
|||||||
assert(p);
|
assert(p);
|
||||||
h->detachFrom(*p);
|
h->detachFrom(*p);
|
||||||
h->attachTo(townAndVis);
|
h->attachTo(townAndVis);
|
||||||
visitingHero = h;
|
h->setVisitedTown(this, false);
|
||||||
h->visitedTown = this;
|
visitingHero = h->id;
|
||||||
h->inTownGarrison = false;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
PlayerState *p = cb->gameState()->getPlayerState(visitingHero->tempOwner);
|
auto oldVisitor = dynamic_cast<CGHeroInstance*>(cb->gameState()->getObjInstance(visitingHero));
|
||||||
visitingHero->visitedTown = nullptr;
|
PlayerState *p = cb->gameState()->getPlayerState(getVisitingHero()->tempOwner);
|
||||||
visitingHero->detachFrom(townAndVis);
|
oldVisitor->setVisitedTown(nullptr, false);
|
||||||
visitingHero->attachTo(*p);
|
oldVisitor->detachFrom(townAndVis);
|
||||||
visitingHero = nullptr;
|
oldVisitor->attachTo(*p);
|
||||||
|
visitingHero = {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CGTownInstance::setGarrisonedHero(CGHeroInstance *h)
|
void CGTownInstance::setGarrisonedHero(CGHeroInstance *h)
|
||||||
{
|
{
|
||||||
if(garrisonHero.get() == h)
|
if(getGarrisonHero() == h)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if(h)
|
if(h)
|
||||||
@ -820,25 +820,40 @@ void CGTownInstance::setGarrisonedHero(CGHeroInstance *h)
|
|||||||
assert(p);
|
assert(p);
|
||||||
h->detachFrom(*p);
|
h->detachFrom(*p);
|
||||||
h->attachTo(*this);
|
h->attachTo(*this);
|
||||||
garrisonHero = h;
|
h->setVisitedTown(this, true);
|
||||||
h->visitedTown = this;
|
garrisonHero = h->id;
|
||||||
h->inTownGarrison = true;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
PlayerState *p = cb->gameState()->getPlayerState(garrisonHero->tempOwner);
|
PlayerState *p = cb->gameState()->getPlayerState(getGarrisonHero()->tempOwner);
|
||||||
garrisonHero->visitedTown = nullptr;
|
auto oldVisitor = dynamic_cast<CGHeroInstance*>(cb->gameState()->getObjInstance(visitingHero));
|
||||||
garrisonHero->inTownGarrison = false;
|
oldVisitor->setVisitedTown(nullptr, false);
|
||||||
garrisonHero->detachFrom(*this);
|
oldVisitor->detachFrom(*this);
|
||||||
garrisonHero->attachTo(*p);
|
oldVisitor->attachTo(*p);
|
||||||
garrisonHero = nullptr;
|
garrisonHero = {};
|
||||||
}
|
}
|
||||||
updateMoraleBonusFromArmy(); //avoid giving morale bonus for same army twice
|
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
|
bool CGTownInstance::armedGarrison() const
|
||||||
{
|
{
|
||||||
return !stacks.empty() || garrisonHero;
|
return !stacks.empty() || getGarrisonHero();
|
||||||
}
|
}
|
||||||
|
|
||||||
int CGTownInstance::getTownLevel() const
|
int CGTownInstance::getTownLevel() const
|
||||||
@ -876,8 +891,8 @@ void CGTownInstance::setNameTextId( const std::string & newName )
|
|||||||
|
|
||||||
const CArmedInstance * CGTownInstance::getUpperArmy() const
|
const CArmedInstance * CGTownInstance::getUpperArmy() const
|
||||||
{
|
{
|
||||||
if(garrisonHero)
|
if(getGarrisonHero())
|
||||||
return garrisonHero;
|
return getGarrisonHero();
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1014,9 +1029,9 @@ CBuilding::TRequired CGTownInstance::genBuildingRequirements(const BuildingID &
|
|||||||
|
|
||||||
void CGTownInstance::addHeroToStructureVisitors(const CGHeroInstance *h, si64 structureInstanceID ) const
|
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
|
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
|
cb->setObjPropertyValue(id, ObjProperty::STRUCTURE_ADD_GARRISONED_HERO, structureInstanceID); //then it must be garrisoned hero
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -11,7 +11,6 @@
|
|||||||
|
|
||||||
#include "IMarket.h"
|
#include "IMarket.h"
|
||||||
#include "CGDwelling.h"
|
#include "CGDwelling.h"
|
||||||
#include "../ConstTransitivePtr.h"
|
|
||||||
#include "../entities/faction/CFaction.h" // TODO: remove
|
#include "../entities/faction/CFaction.h" // TODO: remove
|
||||||
#include "../entities/faction/CTown.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::map<BuildingID, TownRewardableBuildingInstance*> convertOldBuildings(std::vector<TownRewardableBuildingInstance*> oldVector);
|
||||||
std::set<BuildingID> builtBuildings;
|
std::set<BuildingID> builtBuildings;
|
||||||
|
|
||||||
|
ObjectInstanceID garrisonHero;
|
||||||
|
ObjectInstanceID visitingHero;
|
||||||
public:
|
public:
|
||||||
enum EFortLevel {NONE = 0, FORT = 1, CITADEL = 2, CASTLE = 3};
|
enum EFortLevel {NONE = 0, FORT = 1, CITADEL = 2, CASTLE = 3};
|
||||||
|
|
||||||
CTownAndVisitingHero townAndVis;
|
CTownAndVisitingHero townAndVis;
|
||||||
si32 built; //how many buildings has been built this turn
|
si32 built; //how many buildings has been built this turn
|
||||||
si32 destroyed; //how many buildings has been destroyed 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)
|
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
|
PlayerColor alignmentToPlayer; // if set to non-neutral, random town will have same faction as specified player
|
||||||
std::set<BuildingID> forbiddenBuildings;
|
std::set<BuildingID> forbiddenBuildings;
|
||||||
@ -115,6 +115,8 @@ public:
|
|||||||
void setVisitingHero(CGHeroInstance *h);
|
void setVisitingHero(CGHeroInstance *h);
|
||||||
void setGarrisonedHero(CGHeroInstance *h);
|
void setGarrisonedHero(CGHeroInstance *h);
|
||||||
const CArmedInstance *getUpperArmy() const; //garrisoned hero if present or the town itself
|
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 getNameTranslated() const;
|
||||||
std::string getNameTextID() const;
|
std::string getNameTextID() const;
|
||||||
@ -211,7 +213,7 @@ public:
|
|||||||
|
|
||||||
inline bool isBattleOutsideTown(const CGHeroInstance * defendingHero) const
|
inline bool isBattleOutsideTown(const CGHeroInstance * defendingHero) const
|
||||||
{
|
{
|
||||||
return defendingHero && garrisonHero && defendingHero != garrisonHero;
|
return defendingHero && getGarrisonHero() && defendingHero != getGarrisonHero();
|
||||||
}
|
}
|
||||||
protected:
|
protected:
|
||||||
void setPropertyDer(ObjProperty what, ObjPropertyID identifier) override;
|
void setPropertyDer(ObjProperty what, ObjPropertyID identifier) override;
|
||||||
|
@ -616,7 +616,7 @@ bool CGWhirlpool::isProtected(const CGHeroInstance * h)
|
|||||||
{
|
{
|
||||||
return h->hasBonusOfType(BonusType::WHIRLPOOL_PROTECTION)
|
return h->hasBonusOfType(BonusType::WHIRLPOOL_PROTECTION)
|
||||||
|| (h->stacksCount() == 1 && h->Slots().begin()->second->count == 1)
|
|| (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
|
ArtifactID CGArtifact::getArtifact() const
|
||||||
|
@ -872,7 +872,7 @@ void SetSecSkill::applyGs(CGameState *gs)
|
|||||||
|
|
||||||
void SetCommanderProperty::applyGs(CGameState *gs)
|
void SetCommanderProperty::applyGs(CGameState *gs)
|
||||||
{
|
{
|
||||||
CCommanderInstance * commander = gs->getHero(heroid)->commander;
|
const auto & commander = gs->getHero(heroid)->getCommander();
|
||||||
assert (commander);
|
assert (commander);
|
||||||
|
|
||||||
switch (which)
|
switch (which)
|
||||||
@ -1219,15 +1219,14 @@ void RemoveObject::applyGs(CGameState *gs)
|
|||||||
return asi.artifact->getTypeId() == ArtifactID::GRAIL;
|
return asi.artifact->getTypeId() == ArtifactID::GRAIL;
|
||||||
});
|
});
|
||||||
|
|
||||||
if(beatenHero->visitedTown)
|
if(beatenHero->getVisitedTown())
|
||||||
{
|
{
|
||||||
if(beatenHero->visitedTown->garrisonHero == beatenHero)
|
if(beatenHero->getVisitedTown()->getGarrisonHero() == beatenHero)
|
||||||
beatenHero->visitedTown->garrisonHero = nullptr;
|
beatenHero->getVisitedTown()->setGarrisonedHero(nullptr);
|
||||||
else
|
else
|
||||||
beatenHero->visitedTown->visitingHero = nullptr;
|
beatenHero->getVisitedTown()->setVisitingHero(nullptr);
|
||||||
|
|
||||||
beatenHero->visitedTown = nullptr;
|
beatenHero->setVisitedTown(nullptr, false);
|
||||||
beatenHero->inTownGarrison = false;
|
|
||||||
}
|
}
|
||||||
//return hero to the pool, so he may reappear in tavern
|
//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 * v = gs->getHero(visiting);
|
||||||
CGHeroInstance * g = gs->getHero(garrison);
|
CGHeroInstance * g = gs->getHero(garrison);
|
||||||
|
|
||||||
bool newVisitorComesFromGarrison = v && v == t->garrisonHero;
|
bool newVisitorComesFromGarrison = v && v == t->getGarrisonHero();
|
||||||
bool newGarrisonComesFromVisiting = g && g == t->visitingHero;
|
bool newGarrisonComesFromVisiting = g && g == t->getVisitingHero();
|
||||||
|
|
||||||
if(newVisitorComesFromGarrison)
|
if(newVisitorComesFromGarrison)
|
||||||
t->setGarrisonedHero(nullptr);
|
t->setGarrisonedHero(nullptr);
|
||||||
@ -1493,7 +1492,7 @@ void GiveHero::applyGs(CGameState *gs)
|
|||||||
gs->getPlayerState(h->getOwner())->addOwnedObject(h);
|
gs->getPlayerState(h->getOwner())->addOwnedObject(h);
|
||||||
|
|
||||||
gs->getMap().addBlockVisTiles(h);
|
gs->getMap().addBlockVisTiles(h);
|
||||||
h->inTownGarrison = false;
|
h->setVisitedTown(nullptr, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NewObject::applyGs(CGameState *gs)
|
void NewObject::applyGs(CGameState *gs)
|
||||||
@ -2032,7 +2031,7 @@ void CommanderLevelUp::applyGs(CGameState *gs)
|
|||||||
{
|
{
|
||||||
auto * hero = gs->getHero(heroId);
|
auto * hero = gs->getHero(heroId);
|
||||||
assert(hero);
|
assert(hero);
|
||||||
auto commander = hero->commander;
|
const auto & commander = hero->getCommander();
|
||||||
assert(commander);
|
assert(commander);
|
||||||
commander->levelUp();
|
commander->levelUp();
|
||||||
}
|
}
|
||||||
@ -2128,9 +2127,9 @@ void BattleResultAccepted::applyGs(CGameState *gs)
|
|||||||
// Grow up growing artifacts
|
// Grow up growing artifacts
|
||||||
if(const auto winnerHero = gs->getHero(heroResult[winnerSide].heroId))
|
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();
|
art.second.artifact->growingUp();
|
||||||
}
|
}
|
||||||
for(auto & art : winnerHero->artifactsWorn)
|
for(auto & art : winnerHero->artifactsWorn)
|
||||||
|
@ -268,7 +268,7 @@ TeleporterTilesVector CPathfinderHelper::getCastleGates(const PathNodeInfo & sou
|
|||||||
|
|
||||||
for(const auto & town : getPlayerState(hero->tempOwner)->getTowns())
|
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))
|
&& town->hasBuilt(BuildingSubID::CASTLE_GATE))
|
||||||
{
|
{
|
||||||
allowedExits.push_back(town->visitablePos());
|
allowedExits.push_back(town->visitablePos());
|
||||||
|
@ -70,8 +70,8 @@ class BinaryDeserializer : public CLoaderBase
|
|||||||
{
|
{
|
||||||
auto * hero = dynamic_cast<CGHeroInstance *>(armyPtr);
|
auto * hero = dynamic_cast<CGHeroInstance *>(armyPtr);
|
||||||
assert(hero);
|
assert(hero);
|
||||||
assert(hero->commander);
|
assert(hero->getCommander());
|
||||||
data = hero->commander;
|
data = hero->getCommander();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -43,7 +43,7 @@ bool AdventureSpellMechanics::canBeCast(spells::Problem & problem, const CGameIn
|
|||||||
|
|
||||||
if (heroCaster)
|
if (heroCaster)
|
||||||
{
|
{
|
||||||
if(heroCaster->inTownGarrison)
|
if(heroCaster->isGarrisoned())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const auto level = heroCaster->getSpellSchoolLevel(owner);
|
const auto level = heroCaster->getSpellSchoolLevel(owner);
|
||||||
@ -467,7 +467,7 @@ ESpellCastResult TownPortalMechanics::applyAdventureEffects(SpellCastEnvironment
|
|||||||
if(static_cast<int>(parameters.caster->getHeroCaster()->movementPointsRemaining()) < moveCost)
|
if(static_cast<int>(parameters.caster->getHeroCaster()->movementPointsRemaining()) < moveCost)
|
||||||
return ESpellCastResult::ERROR;
|
return ESpellCastResult::ERROR;
|
||||||
|
|
||||||
if(destination->visitingHero)
|
if(destination->getVisitingHero())
|
||||||
{
|
{
|
||||||
InfoWindow iw;
|
InfoWindow iw;
|
||||||
iw.player = parameters.caster->getCasterOwner();
|
iw.player = parameters.caster->getCasterOwner();
|
||||||
@ -520,7 +520,7 @@ ESpellCastResult TownPortalMechanics::applyAdventureEffects(SpellCastEnvironment
|
|||||||
return ESpellCastResult::ERROR;
|
return ESpellCastResult::ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(destination->visitingHero)
|
if(destination->getVisitingHero())
|
||||||
{
|
{
|
||||||
env->complain("[Internal error] Can't teleport to occupied town");
|
env->complain("[Internal error] Can't teleport to occupied town");
|
||||||
return ESpellCastResult::ERROR;
|
return ESpellCastResult::ERROR;
|
||||||
@ -635,7 +635,7 @@ ESpellCastResult TownPortalMechanics::beginCast(SpellCastEnvironment * env, cons
|
|||||||
|
|
||||||
for(const auto * t : towns)
|
for(const auto * t : towns)
|
||||||
{
|
{
|
||||||
if(t->visitingHero == nullptr) //empty town
|
if(t->getVisitingHero() == nullptr) //empty town
|
||||||
request.objects.push_back(t->id);
|
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)
|
std::shared_ptr<QImage> MapHandler::getObjectImage(const CGObjectInstance * obj)
|
||||||
{
|
{
|
||||||
if( !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)
|
|| (obj->ID==Obj::BOAT && static_cast<const CGBoat*>(obj)->hero)) //boat with hero (hero graphics is used)
|
||||||
{
|
{
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -334,8 +334,8 @@ void CGameHandler::expGiven(const CGHeroInstance *hero)
|
|||||||
{
|
{
|
||||||
if (hero->gainsLevel())
|
if (hero->gainsLevel())
|
||||||
levelUpHero(hero);
|
levelUpHero(hero);
|
||||||
else if (hero->commander && hero->commander->gainsLevel())
|
else if (hero->getCommander() && hero->getCommander()->gainsLevel())
|
||||||
levelUpCommander(hero->commander);
|
levelUpCommander(hero->getCommander());
|
||||||
|
|
||||||
//if (hero->commander && hero->level > hero->commander->level && hero->commander->gainsLevel())
|
//if (hero->commander && hero->level > hero->commander->level && hero->commander->gainsLevel())
|
||||||
// levelUpCommander(hero->commander);
|
// levelUpCommander(hero->commander);
|
||||||
@ -375,7 +375,7 @@ void CGameHandler::giveExperience(const CGHeroInstance * hero, TExpType amountTo
|
|||||||
sendAndApply(sps);
|
sendAndApply(sps);
|
||||||
|
|
||||||
//hero may level up
|
//hero may level up
|
||||||
if (hero->commander && hero->commander->alive)
|
if (hero->getCommander() && hero->getCommander()->alive)
|
||||||
{
|
{
|
||||||
//FIXME: trim experience according to map limit?
|
//FIXME: trim experience according to map limit?
|
||||||
SetCommanderProperty scp;
|
SetCommanderProperty scp;
|
||||||
@ -412,8 +412,8 @@ void CGameHandler::changeSecSkill(const CGHeroInstance * hero, SecondarySkill wh
|
|||||||
sss.abs = abs;
|
sss.abs = abs;
|
||||||
sendAndApply(sss);
|
sendAndApply(sss);
|
||||||
|
|
||||||
if (hero->visitedTown)
|
if (hero->getVisitedTown())
|
||||||
giveSpells(hero->visitedTown, hero);
|
giveSpells(hero->getVisitedTown(), hero);
|
||||||
|
|
||||||
// Our scouting range may have changed - update it
|
// Our scouting range may have changed - update it
|
||||||
if (hero->getOwner().isValidPlayer())
|
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)
|
if(distance(h->pos, dst) >= 1.5 && movementMode == EMovementMode::STANDARD)
|
||||||
return complainRet("Tiles " + h->pos.toString()+ " and "+ dst.toString() +" are not neighboring!");
|
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!");
|
return complainRet("Can not move garrisoned hero!");
|
||||||
|
|
||||||
if(h->movementPointsRemaining() < cost && dst != h->pos && movementMode == EMovementMode::STANDARD)
|
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)
|
if (!h || !t)
|
||||||
COMPLAIN_RET("Invalid call to teleportHero!");
|
COMPLAIN_RET("Invalid call to teleportHero!");
|
||||||
|
|
||||||
const CGTownInstance *from = h->visitedTown;
|
const CGTownInstance *from = h->getVisitedTown();
|
||||||
if (((h->getOwner() != t->getOwner())
|
if (((h->getOwner() != t->getOwner())
|
||||||
&& complain("Cannot teleport hero to another player"))
|
&& 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)
|
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;
|
HeroVisitCastle vc;
|
||||||
vc.hid = hero->id;
|
vc.hid = hero->id;
|
||||||
@ -1196,8 +1196,8 @@ void CGameHandler::heroVisitCastle(const CGTownInstance * obj, const CGHeroInsta
|
|||||||
}
|
}
|
||||||
visitCastleObjects(obj, hero);
|
visitCastleObjects(obj, hero);
|
||||||
|
|
||||||
if (obj->visitingHero && obj->garrisonHero)
|
if (obj->getVisitingHero() && obj->getGarrisonHero())
|
||||||
useScholarSkill(obj->visitingHero->id, obj->garrisonHero->id);
|
useScholarSkill(obj->getVisitingHero()->id, obj->getGarrisonHero()->id);
|
||||||
checkVictoryLossConditionsForPlayer(hero->tempOwner); //transported artifact?
|
checkVictoryLossConditionsForPlayer(hero->tempOwner); //transported artifact?
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2073,10 +2073,10 @@ bool CGameHandler::buildStructure(ObjectInstanceID tid, BuildingID requestedID,
|
|||||||
case CBuilding::BUILD_GRAIL :
|
case CBuilding::BUILD_GRAIL :
|
||||||
if(requestedBuilding->mode == CBuilding::BUILD_GRAIL) //needs 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!")
|
COMPLAIN_RET("Cannot build this without grail!")
|
||||||
else
|
else
|
||||||
removeArtifact(ArtifactLocation(t->visitingHero->id, t->visitingHero->getArtPos(ArtifactID::GRAIL, false)));
|
removeArtifact(ArtifactLocation(t->getVisitingHero()->id, t->getVisitingHero()->getArtPos(ArtifactID::GRAIL, false)));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -2123,10 +2123,10 @@ bool CGameHandler::buildStructure(ObjectInstanceID tid, BuildingID requestedID,
|
|||||||
|
|
||||||
if(isMageGuild || isLibrary || (t->getFactionID() == ETownType::CONFLUX && buildingID == BuildingID::GRAIL))
|
if(isMageGuild || isLibrary || (t->getFactionID() == ETownType::CONFLUX && buildingID == BuildingID::GRAIL))
|
||||||
{
|
{
|
||||||
if(t->visitingHero)
|
if(t->getVisitingHero())
|
||||||
giveSpells(t,t->visitingHero);
|
giveSpells(t,t->getVisitingHero());
|
||||||
if(t->garrisonHero)
|
if(t->getGarrisonHero())
|
||||||
giveSpells(t,t->garrisonHero);
|
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
|
//garrison hero first - consistent with original H3 Mana Vortex and Battle Scholar Academy levelup windows order
|
||||||
std::vector<const CGHeroInstance *> visitors;
|
std::vector<const CGHeroInstance *> visitors;
|
||||||
if (t->garrisonHero)
|
if (t->getGarrisonHero())
|
||||||
visitors.push_back(t->garrisonHero);
|
visitors.push_back(t->getGarrisonHero());
|
||||||
if (t->visitingHero)
|
if (t->getVisitingHero())
|
||||||
visitors.push_back(t->visitingHero);
|
visitors.push_back(t->getVisitingHero());
|
||||||
|
|
||||||
if (!visitors.empty())
|
if (!visitors.empty())
|
||||||
visitCastleObjects(t, visitors);
|
visitCastleObjects(t, visitors);
|
||||||
@ -2233,12 +2233,12 @@ bool CGameHandler::visitTownBuilding(ObjectInstanceID tid, BuildingID bid)
|
|||||||
return true;
|
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<BuildingID> buildingsToVisit;
|
||||||
std::vector<const CGHeroInstance*> visitors;
|
std::vector<const CGHeroInstance*> visitors;
|
||||||
buildingsToVisit.push_back(bid);
|
buildingsToVisit.push_back(bid);
|
||||||
visitors.push_back(t->visitingHero);
|
visitors.push_back(t->getVisitingHero());
|
||||||
auto visitQuery = std::make_shared<TownBuildingVisitQuery>(this, t, visitors, buildingsToVisit);
|
auto visitQuery = std::make_shared<TownBuildingVisitQuery>(this, t, visitors, buildingsToVisit);
|
||||||
queries->addQuery(visitQuery);
|
queries->addQuery(visitQuery);
|
||||||
return true;
|
return true;
|
||||||
@ -2316,10 +2316,10 @@ bool CGameHandler::spellResearch(ObjectInstanceID tid, SpellID spellAtSlot, bool
|
|||||||
|
|
||||||
setResearchedSpells(t, level, spells, accepted);
|
setResearchedSpells(t, level, spells, accepted);
|
||||||
|
|
||||||
if(t->visitingHero)
|
if(t->getVisitingHero())
|
||||||
giveSpells(t, t->visitingHero);
|
giveSpells(t, t->getVisitingHero());
|
||||||
if(t->garrisonHero)
|
if(t->getGarrisonHero())
|
||||||
giveSpells(t, t->garrisonHero);
|
giveSpells(t, t->getGarrisonHero());
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -2342,7 +2342,7 @@ bool CGameHandler::recruitCreatures(ObjectInstanceID objid, ObjectInstanceID dst
|
|||||||
if (town)
|
if (town)
|
||||||
{
|
{
|
||||||
COMPLAIN_RET_FALSE_IF(town != army && !hero, "Cannot recruit: invalid destination!");
|
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
|
else
|
||||||
{
|
{
|
||||||
@ -2505,16 +2505,16 @@ bool CGameHandler::swapGarrisonOnSiege(ObjectInstanceID tid)
|
|||||||
{
|
{
|
||||||
const CGTownInstance * town = getTown(tid);
|
const CGTownInstance * town = getTown(tid);
|
||||||
|
|
||||||
if(!town->garrisonHero == !town->visitingHero)
|
if(!town->getGarrisonHero() == !town->getVisitingHero())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
SetHeroesInTown intown;
|
SetHeroesInTown intown;
|
||||||
intown.tid = tid;
|
intown.tid = tid;
|
||||||
|
|
||||||
if(town->garrisonHero) //garrison -> vising
|
if(town->getGarrisonHero()) //garrison -> vising
|
||||||
{
|
{
|
||||||
intown.garrison = ObjectInstanceID();
|
intown.garrison = ObjectInstanceID();
|
||||||
intown.visiting = town->garrisonHero->id;
|
intown.visiting = town->getGarrisonHero()->id;
|
||||||
}
|
}
|
||||||
else //visiting -> garrison
|
else //visiting -> garrison
|
||||||
{
|
{
|
||||||
@ -2522,7 +2522,7 @@ bool CGameHandler::swapGarrisonOnSiege(ObjectInstanceID tid)
|
|||||||
town->mergeGarrisonOnSiege();
|
town->mergeGarrisonOnSiege();
|
||||||
|
|
||||||
intown.visiting = ObjectInstanceID();
|
intown.visiting = ObjectInstanceID();
|
||||||
intown.garrison = town->visitingHero->id;
|
intown.garrison = town->getVisitingHero()->id;
|
||||||
}
|
}
|
||||||
sendAndApply(intown);
|
sendAndApply(intown);
|
||||||
return true;
|
return true;
|
||||||
@ -2531,29 +2531,29 @@ bool CGameHandler::swapGarrisonOnSiege(ObjectInstanceID tid)
|
|||||||
bool CGameHandler::garrisonSwap(ObjectInstanceID tid)
|
bool CGameHandler::garrisonSwap(ObjectInstanceID tid)
|
||||||
{
|
{
|
||||||
const CGTownInstance * town = getTown(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!");
|
complain("Cannot make garrison swap, not enough free slots!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
moveArmy(town, town->visitingHero, true);
|
moveArmy(town, town->getVisitingHero(), true);
|
||||||
|
|
||||||
SetHeroesInTown intown;
|
SetHeroesInTown intown;
|
||||||
intown.tid = tid;
|
intown.tid = tid;
|
||||||
intown.visiting = ObjectInstanceID();
|
intown.visiting = ObjectInstanceID();
|
||||||
intown.garrison = town->visitingHero->id;
|
intown.garrison = town->getVisitingHero()->id;
|
||||||
sendAndApply(intown);
|
sendAndApply(intown);
|
||||||
return true;
|
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);
|
int mapCap = getSettings().getInteger(EGameSettings::HEROES_PER_PLAYER_ON_MAP_CAP);
|
||||||
//check if moving hero out of town will break wandering heroes limit
|
//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!");
|
complain("Cannot move hero out of the garrison, there are already " + std::to_string(mapCap) + " wandering heroes!");
|
||||||
return false;
|
return false;
|
||||||
@ -2562,16 +2562,16 @@ bool CGameHandler::garrisonSwap(ObjectInstanceID tid)
|
|||||||
SetHeroesInTown intown;
|
SetHeroesInTown intown;
|
||||||
intown.tid = tid;
|
intown.tid = tid;
|
||||||
intown.garrison = ObjectInstanceID();
|
intown.garrison = ObjectInstanceID();
|
||||||
intown.visiting = town->garrisonHero->id;
|
intown.visiting = town->getGarrisonHero()->id;
|
||||||
sendAndApply(intown);
|
sendAndApply(intown);
|
||||||
return true;
|
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;
|
SetHeroesInTown intown;
|
||||||
intown.tid = tid;
|
intown.tid = tid;
|
||||||
intown.garrison = town->visitingHero->id;
|
intown.garrison = town->getVisitingHero()->id;
|
||||||
intown.visiting = town->garrisonHero->id;
|
intown.visiting = town->getGarrisonHero()->id;
|
||||||
sendAndApply(intown);
|
sendAndApply(intown);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -2991,7 +2991,7 @@ bool CGameHandler::buyArtifact(ObjectInstanceID hid, ArtifactID aid)
|
|||||||
{
|
{
|
||||||
const CGHeroInstance * hero = getHero(hid);
|
const CGHeroInstance * hero = getHero(hid);
|
||||||
COMPLAIN_RET_FALSE_IF(nullptr == hero, "Invalid hero index");
|
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");
|
COMPLAIN_RET_FALSE_IF(nullptr == town, "Hero not in town");
|
||||||
|
|
||||||
if (aid==ArtifactID::SPELLBOOK)
|
if (aid==ArtifactID::SPELLBOOK)
|
||||||
@ -3342,13 +3342,13 @@ bool CGameHandler::isAllowedExchange(ObjectInstanceID id1, ObjectInstanceID id2)
|
|||||||
if (o1->ID == Obj::TOWN)
|
if (o1->ID == Obj::TOWN)
|
||||||
{
|
{
|
||||||
const CGTownInstance *t = static_cast<const CGTownInstance*>(o1);
|
const CGTownInstance *t = static_cast<const CGTownInstance*>(o1);
|
||||||
if (t->visitingHero == o2 || t->garrisonHero == o2)
|
if (t->getVisitingHero() == o2 || t->getGarrisonHero() == o2)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (o2->ID == Obj::TOWN)
|
if (o2->ID == Obj::TOWN)
|
||||||
{
|
{
|
||||||
const CGTownInstance *t = static_cast<const CGTownInstance*>(o2);
|
const CGTownInstance *t = static_cast<const CGTownInstance*>(o2);
|
||||||
if (t->visitingHero == o1 || t->garrisonHero == o1)
|
if (t->getVisitingHero() == o1 || t->getGarrisonHero() == o1)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3364,7 +3364,7 @@ bool CGameHandler::isAllowedExchange(ObjectInstanceID id1, ObjectInstanceID id2)
|
|||||||
const CGHeroInstance *h2 = static_cast<const CGHeroInstance*>(o2);
|
const CGHeroInstance *h2 = static_cast<const CGHeroInstance*>(o2);
|
||||||
|
|
||||||
// two heroes in same town (garrisoned and visiting)
|
// 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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3408,7 +3408,7 @@ void CGameHandler::objectVisited(const CGObjectInstance * obj, const CGHeroInsta
|
|||||||
if(obj->ID == Obj::HERO)
|
if(obj->ID == Obj::HERO)
|
||||||
{
|
{
|
||||||
auto visitedHero = static_cast<const CGHeroInstance *>(obj);
|
auto visitedHero = static_cast<const CGHeroInstance *>(obj);
|
||||||
const auto visitedTown = visitedHero->visitedTown;
|
const auto visitedTown = visitedHero->getVisitedTown();
|
||||||
|
|
||||||
if(visitedTown)
|
if(visitedTown)
|
||||||
{
|
{
|
||||||
|
@ -183,7 +183,7 @@ void ApplyGhNetPackVisitor::visitUpgradeCreature(UpgradeCreature & pack)
|
|||||||
void ApplyGhNetPackVisitor::visitGarrisonHeroSwap(GarrisonHeroSwap & pack)
|
void ApplyGhNetPackVisitor::visitGarrisonHeroSwap(GarrisonHeroSwap & pack)
|
||||||
{
|
{
|
||||||
const CGTownInstance * town = gh.getTown(pack.tid);
|
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.throwNotAllowedAction(connection); //neither town nor garrisoned hero (if present) is ours
|
||||||
gh.throwIfPlayerNotActive(connection, &pack);
|
gh.throwIfPlayerNotActive(connection, &pack);
|
||||||
|
|
||||||
|
@ -106,7 +106,7 @@ CasualtiesAfterBattle::CasualtiesAfterBattle(const CBattleInfoCallback & battle,
|
|||||||
if(c)
|
if(c)
|
||||||
{
|
{
|
||||||
auto h = dynamic_cast <const CGHeroInstance *>(army);
|
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.");
|
logGlobal->debug("Commander is dead.");
|
||||||
heroWithDeadCommander = army->id; //TODO: unify commander handling
|
heroWithDeadCommander = army->id; //TODO: unify commander handling
|
||||||
@ -323,11 +323,11 @@ void BattleResultProcessor::endBattleConfirm(const CBattleInfoCallback & battle)
|
|||||||
|
|
||||||
if(battleResult->winner == BattleSide::DEFENDER
|
if(battleResult->winner == BattleSide::DEFENDER
|
||||||
&& winnerHero
|
&& winnerHero
|
||||||
&& winnerHero->visitedTown
|
&& winnerHero->getVisitedTown()
|
||||||
&& !winnerHero->inTownGarrison
|
&& !winnerHero->isGarrisoned()
|
||||||
&& winnerHero->visitedTown->garrisonHero == winnerHero)
|
&& 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
|
//give exp
|
||||||
if(!finishingBattle->isDraw() && battleResult->exp[finishingBattle->winnerSide] && winnerHero)
|
if(!finishingBattle->isDraw() && battleResult->exp[finishingBattle->winnerSide] && winnerHero)
|
||||||
@ -336,7 +336,7 @@ void BattleResultProcessor::endBattleConfirm(const CBattleInfoCallback & battle)
|
|||||||
// Add statistics
|
// Add statistics
|
||||||
if(loserHero && !finishingBattle->isDraw())
|
if(loserHero && !finishingBattle->isDraw())
|
||||||
{
|
{
|
||||||
ConstTransitivePtr<CGHeroInstance> strongestHero = nullptr;
|
const CGHeroInstance * strongestHero = nullptr;
|
||||||
for(auto & hero : gameHandler->gameState()->getPlayerState(finishingBattle->loser)->getHeroes())
|
for(auto & hero : gameHandler->gameState()->getPlayerState(finishingBattle->loser)->getHeroes())
|
||||||
if(!strongestHero || hero->exp > strongestHero->exp)
|
if(!strongestHero || hero->exp > strongestHero->exp)
|
||||||
strongestHero = hero;
|
strongestHero = hero;
|
||||||
@ -460,11 +460,11 @@ void BattleResultProcessor::battleFinalize(const BattleID & battleID, const Batt
|
|||||||
addArtifactToTransfer(packHero, loserHero->getArtPos(art), art);
|
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);
|
auto & packCommander = resultsApplied.artifacts.emplace_back(finishingBattle->victor, finishingBattle->loserId, finishingBattle->winnerId, false);
|
||||||
packCommander.srcCreature = loserHero->findStack(loserHero->commander);
|
packCommander.srcCreature = loserHero->findStack(loserHero->getCommander());
|
||||||
for(const auto & artSlot : loserHero->commander->artifactsWorn)
|
for(const auto & artSlot : loserHero->getCommander()->artifactsWorn)
|
||||||
addArtifactToTransfer(packCommander, artSlot.first, artSlot.second.getArt());
|
addArtifactToTransfer(packCommander, artSlot.first, artSlot.second.getArt());
|
||||||
}
|
}
|
||||||
auto armyObj = dynamic_cast<const CArmedInstance*>(gameHandler->getObj(finishingBattle->loserId));
|
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!"))
|
if(!town->hasBuilt(BuildingID::TAVERN) && gameHandler->complain("No tavern!"))
|
||||||
return false;
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,11 +143,11 @@ void NewTurnProcessor::onPlayerTurnStarted(PlayerColor which)
|
|||||||
for (const auto * t : playerState->getTowns())
|
for (const auto * t : playerState->getTowns())
|
||||||
{
|
{
|
||||||
//garrison hero first - consistent with original H3 Mana Vortex and Battle Scholar Academy levelup windows order
|
//garrison hero first - consistent with original H3 Mana Vortex and Battle Scholar Academy levelup windows order
|
||||||
if (t->garrisonHero != nullptr)
|
if (t->getGarrisonHero() != nullptr)
|
||||||
gameHandler->objectVisited(t, t->garrisonHero);
|
gameHandler->objectVisited(t, t->getGarrisonHero());
|
||||||
|
|
||||||
if (t->visitingHero != nullptr)
|
if (t->getVisitingHero() != nullptr)
|
||||||
gameHandler->objectVisited(t, t->visitingHero);
|
gameHandler->objectVisited(t, t->getVisitingHero());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -773,7 +773,7 @@ void PlayerMessageProcessor::executeCheatCode(const std::string & cheatName, Pla
|
|||||||
const CGHeroInstance * hero = gameHandler->getHero(currObj);
|
const CGHeroInstance * hero = gameHandler->getHero(currObj);
|
||||||
const CGTownInstance * town = gameHandler->getTown(currObj);
|
const CGTownInstance * town = gameHandler->getTown(currObj);
|
||||||
if (!town && hero)
|
if (!town && hero)
|
||||||
town = hero->visitedTown;
|
town = hero->getVisitedTown();
|
||||||
|
|
||||||
const auto & doCheatGiveSpells = [&]() { cheatGiveSpells(player, hero); };
|
const auto & doCheatGiveSpells = [&]() { cheatGiveSpells(player, hero); };
|
||||||
const auto & doCheatBuildTown = [&]() { cheatBuildTown(player, town); };
|
const auto & doCheatBuildTown = [&]() { cheatBuildTown(player, town); };
|
||||||
|
@ -237,7 +237,7 @@ void CCommanderLevelUpDialogQuery::onRemoval(PlayerColor color)
|
|||||||
{
|
{
|
||||||
assert(answer);
|
assert(answer);
|
||||||
logGlobal->trace("Completing commander level-up query. Commander of hero %s gains skill %s", hero->getObjectName(), answer.value());
|
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
|
void CCommanderLevelUpDialogQuery::notifyObjectAboutRemoval(const CGObjectInstance * visitedObject, const CGHeroInstance * visitingHero) const
|
||||||
|
Loading…
x
Reference in New Issue
Block a user