mirror of
https://github.com/vcmi/vcmi.git
synced 2025-11-27 22:49:25 +02:00
more thread_local removal in NK2, still WIP
This commit is contained in:
@@ -46,7 +46,7 @@ void BuildAnalyzer::update()
|
|||||||
|
|
||||||
for(const CGTownInstance * town : towns)
|
for(const CGTownInstance * town : towns)
|
||||||
{
|
{
|
||||||
if(town->built >= ccTl->getSettings().getInteger(EGameSettings::TOWNS_BUILDINGS_PER_TURN_CAP))
|
if(town->built >= aiNk->cc->getSettings().getInteger(EGameSettings::TOWNS_BUILDINGS_PER_TURN_CAP))
|
||||||
continue; // Not much point in trying anything - can't built in this town anymore today
|
continue; // Not much point in trying anything - can't built in this town anymore today
|
||||||
|
|
||||||
#if NK2AI_TRACE_LEVEL >= 1
|
#if NK2AI_TRACE_LEVEL >= 1
|
||||||
|
|||||||
@@ -310,13 +310,9 @@ void ObjectClusterizer::clusterize()
|
|||||||
{
|
{
|
||||||
for(auto id : invalidated)
|
for(auto id : invalidated)
|
||||||
{
|
{
|
||||||
auto obj = ccTl->getObj(id, false);
|
if(auto obj = aiNk->cc->getObj(id, false))
|
||||||
|
|
||||||
if(obj)
|
|
||||||
{
|
|
||||||
objs.push_back(obj);
|
objs.push_back(obj);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
invalidated.clear();
|
invalidated.clear();
|
||||||
}
|
}
|
||||||
@@ -353,7 +349,7 @@ void ObjectClusterizer::clusterize()
|
|||||||
|
|
||||||
for(auto pair : blockedObjects)
|
for(auto pair : blockedObjects)
|
||||||
{
|
{
|
||||||
auto blocker = ccTl->getObj(pair.first);
|
auto blocker = aiNk->cc->getObj(pair.first);
|
||||||
|
|
||||||
logAi->trace("Cluster %s %s count: %i", blocker->getObjectName(), blocker->visitablePos().toString(), pair.second->objects.size());
|
logAi->trace("Cluster %s %s count: %i", blocker->getObjectName(), blocker->visitablePos().toString(), pair.second->objects.size());
|
||||||
|
|
||||||
|
|||||||
@@ -27,29 +27,23 @@ std::string BuyArmyBehavior::toString() const
|
|||||||
Goals::TGoalVec BuyArmyBehavior::decompose(const Nullkiller * aiNk) const
|
Goals::TGoalVec BuyArmyBehavior::decompose(const Nullkiller * aiNk) const
|
||||||
{
|
{
|
||||||
Goals::TGoalVec tasks;
|
Goals::TGoalVec tasks;
|
||||||
|
const auto heroes = aiNk->cc->getHeroesInfo();
|
||||||
auto heroes = ccTl->getHeroesInfo();
|
|
||||||
|
|
||||||
if(heroes.empty())
|
if(heroes.empty())
|
||||||
{
|
|
||||||
return tasks;
|
return tasks;
|
||||||
}
|
|
||||||
|
|
||||||
// Simplification: Moved this call before getting into the decomposer
|
// Simplification: Moved this call before getting into the decomposer
|
||||||
// aiNk->dangerHitMap->updateHitMap();
|
// aiNk->dangerHitMap->updateHitMap();
|
||||||
|
|
||||||
for(auto town : ccTl->getTownsInfo())
|
for(const auto town : aiNk->cc->getTownsInfo())
|
||||||
{
|
{
|
||||||
uint8_t closestThreat = aiNk->dangerHitMap->getTileThreat(town->visitablePos()).fastestDanger.turn;
|
uint8_t closestThreat = aiNk->dangerHitMap->getTileThreat(town->visitablePos()).fastestDanger.turn;
|
||||||
|
if(closestThreat >= 2 && aiNk->buildAnalyzer->isGoldPressureOverMax() && !town->hasBuilt(BuildingID::CITY_HALL) &&
|
||||||
if (closestThreat >=2 && aiNk->buildAnalyzer->isGoldPressureOverMax() && !town->hasBuilt(BuildingID::CITY_HALL) && ccTl->canBuildStructure(town, BuildingID::CITY_HALL) != EBuildingState::FORBIDDEN)
|
aiNk->cc->canBuildStructure(town, BuildingID::CITY_HALL) != EBuildingState::FORBIDDEN)
|
||||||
{
|
{
|
||||||
return tasks;
|
return tasks;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto townArmyAvailableToBuy = aiNk->armyManager->getArmyAvailableToBuyAsCCreatureSet(
|
auto townArmyAvailableToBuy = aiNk->armyManager->getArmyAvailableToBuyAsCCreatureSet(town, aiNk->getFreeResources());
|
||||||
town,
|
|
||||||
aiNk->getFreeResources());
|
|
||||||
|
|
||||||
for(const CGHeroInstance * targetHero : heroes)
|
for(const CGHeroInstance * targetHero : heroes)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -50,12 +50,12 @@ Goals::TGoalVec ExplorationBehavior::decompose(const Nullkiller * aiNk) const
|
|||||||
case Obj::SUBTERRANEAN_GATE:
|
case Obj::SUBTERRANEAN_GATE:
|
||||||
case Obj::WHIRLPOOL:
|
case Obj::WHIRLPOOL:
|
||||||
{
|
{
|
||||||
auto tObj = dynamic_cast<const CGTeleport*>(obj);
|
const auto tObj = dynamic_cast<const CGTeleport*>(obj);
|
||||||
for (auto exit : ccTl->getTeleportChannelExits(tObj->channel))
|
for (auto exit : aiNk->cc->getTeleportChannelExits(tObj->channel))
|
||||||
{
|
{
|
||||||
if (exit != tObj->id)
|
if (exit != tObj->id)
|
||||||
{
|
{
|
||||||
if (!ccTl->isVisible(ccTl->getObjInstance(exit)))
|
if (!aiNk->cc->isVisible(aiNk->cc->getObjInstance(exit)))
|
||||||
tasks.push_back(sptr(Composition().addNext(ExplorationPoint(obj->visitablePos(), 50)).addNext(CaptureObject(obj))));
|
tasks.push_back(sptr(Composition().addNext(ExplorationPoint(obj->visitablePos(), 50)).addNext(CaptureObject(obj))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -312,7 +312,7 @@ Goals::TGoalVec GatherArmyBehavior::upgradeArmy(const Nullkiller * aiNk, const C
|
|||||||
&& aiNk->heroManager->canRecruitHero(upgrader)
|
&& aiNk->heroManager->canRecruitHero(upgrader)
|
||||||
&& path.turn() < aiNk->settings->getScoutHeroTurnDistanceLimit()) // TODO: Mircea: Inspect what this does
|
&& path.turn() < aiNk->settings->getScoutHeroTurnDistanceLimit()) // TODO: Mircea: Inspect what this does
|
||||||
{
|
{
|
||||||
for(auto hero : ccTl->getAvailableHeroes(upgrader))
|
for(const auto * const hero : aiNk->cc->getAvailableHeroes(upgrader))
|
||||||
{
|
{
|
||||||
auto scoutReinforcement = aiNk->armyManager->howManyReinforcementsCanGet(hero, upgrader);
|
auto scoutReinforcement = aiNk->armyManager->howManyReinforcementsCanGet(hero, upgrader);
|
||||||
|
|
||||||
|
|||||||
@@ -97,15 +97,15 @@ bool needToRecruitHero(const Nullkiller * aiNk, const CGTownInstance * startupTo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto basicCount = ccTl->getTownsInfo().size() + 2;
|
const auto basicCount = aiNk->cc->getTownsInfo().size() + 2;
|
||||||
auto boost = std::min(
|
const auto boost = std::min(
|
||||||
(int)std::floor(std::pow(1 + (ccTl->getMapSize().x / 50), 2)),
|
(int)std::floor(std::pow(1 + aiNk->cc->getMapSize().x / 50, 2)),
|
||||||
treasureSourcesCount / 2);
|
treasureSourcesCount / 2);
|
||||||
|
|
||||||
logAi->trace("Treasure sources found %d", treasureSourcesCount);
|
logAi->trace("Treasure sources found %d", treasureSourcesCount);
|
||||||
logAi->trace("Startup allows %d+%d heroes", basicCount, boost);
|
logAi->trace("Startup allows %d+%d heroes", basicCount, boost);
|
||||||
|
|
||||||
return ccTl->getHeroCount(aiNk->playerID, true) < basicCount + boost;
|
return aiNk->cc->getHeroCount(aiNk->playerID, true) < basicCount + boost;
|
||||||
}
|
}
|
||||||
|
|
||||||
Goals::TGoalVec StartupBehavior::decompose(const Nullkiller * aiNk) const
|
Goals::TGoalVec StartupBehavior::decompose(const Nullkiller * aiNk) const
|
||||||
|
|||||||
@@ -583,7 +583,7 @@ float RewardEvaluator::evaluateWitchHutSkillScore(const CGObjectInstance * hut,
|
|||||||
return role == HeroRole::SCOUT ? 2 : 0;
|
return role == HeroRole::SCOUT ? 2 : 0;
|
||||||
|
|
||||||
if(hero->getSecSkillLevel(skill) != MasteryLevel::NONE
|
if(hero->getSecSkillLevel(skill) != MasteryLevel::NONE
|
||||||
|| static_cast<int>(hero->secSkills.size()) >= ccTl->getSettings().getInteger(EGameSettings::HEROES_SKILL_PER_HERO))
|
|| static_cast<int>(hero->secSkills.size()) >= aiNk->cc->getSettings().getInteger(EGameSettings::HEROES_SKILL_PER_HERO))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
auto score = aiNk->heroManager->evaluateSecSkill(skill, hero);
|
auto score = aiNk->heroManager->evaluateSecSkill(skill, hero);
|
||||||
|
|||||||
@@ -59,10 +59,9 @@ void AdventureSpellCast::accept(AIGateway * aiGw)
|
|||||||
if (hero->isGarrisoned())
|
if (hero->isGarrisoned())
|
||||||
aiGw->cc->swapGarrisonHero(hero->getVisitedTown());
|
aiGw->cc->swapGarrisonHero(hero->getVisitedTown());
|
||||||
|
|
||||||
auto wait = ccTl->waitTillRealize;
|
const auto wait = aiGw->cc->waitTillRealize;
|
||||||
|
aiGw->cc->waitTillRealize = true;
|
||||||
ccTl->waitTillRealize = true;
|
aiGw->cc->castSpell(hero, spellID, tile);
|
||||||
ccTl->castSpell(hero, spellID, tile);
|
|
||||||
|
|
||||||
if(town && townPortalEffect)
|
if(town && townPortalEffect)
|
||||||
{
|
{
|
||||||
@@ -70,8 +69,7 @@ void AdventureSpellCast::accept(AIGateway * aiGw)
|
|||||||
aiGw->moveHeroToTile(town->visitablePos(), HeroPtr(hero, aiGw->cc));
|
aiGw->moveHeroToTile(town->visitablePos(), HeroPtr(hero, aiGw->cc));
|
||||||
}
|
}
|
||||||
|
|
||||||
ccTl->waitTillRealize = wait;
|
aiGw->cc->waitTillRealize = wait;
|
||||||
|
|
||||||
throw goalFulfilledException(sptr(*this));
|
throw goalFulfilledException(sptr(*this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -45,12 +45,12 @@ void BuildBoat::accept(AIGateway * aiGw)
|
|||||||
TResources boatCost;
|
TResources boatCost;
|
||||||
shipyard->getBoatCost(boatCost);
|
shipyard->getBoatCost(boatCost);
|
||||||
|
|
||||||
if(!ccTl->getResourceAmount().canAfford(boatCost))
|
if(!aiGw->cc->getResourceAmount().canAfford(boatCost))
|
||||||
{
|
{
|
||||||
throw cannotFulfillGoalException("Can not afford boat");
|
throw cannotFulfillGoalException("Can not afford boat");
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ccTl->getPlayerRelations(aiGw->playerID, shipyard->getObject()->getOwner()) == PlayerRelations::ENEMIES)
|
if(aiGw->cc->getPlayerRelations(aiGw->playerID, shipyard->getObject()->getOwner()) == PlayerRelations::ENEMIES)
|
||||||
{
|
{
|
||||||
throw cannotFulfillGoalException("Can not build boat in enemy shipyard");
|
throw cannotFulfillGoalException("Can not build boat in enemy shipyard");
|
||||||
}
|
}
|
||||||
@@ -65,7 +65,7 @@ void BuildBoat::accept(AIGateway * aiGw)
|
|||||||
shipyard->getObject()->visitablePos().toString(),
|
shipyard->getObject()->visitablePos().toString(),
|
||||||
shipyard->bestLocation().toString());
|
shipyard->bestLocation().toString());
|
||||||
|
|
||||||
ccTl->buildBoat(shipyard);
|
aiGw->cc->buildBoat(shipyard);
|
||||||
|
|
||||||
throw goalFulfilledException(sptr(*this));
|
throw goalFulfilledException(sptr(*this));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,11 +52,11 @@ void BuildThis::accept(AIGateway * aiGw)
|
|||||||
|
|
||||||
if(town)
|
if(town)
|
||||||
{
|
{
|
||||||
if(ccTl->canBuildStructure(town, b) == EBuildingState::ALLOWED)
|
if(aiGw->cc->canBuildStructure(town, b) == EBuildingState::ALLOWED)
|
||||||
{
|
{
|
||||||
logAi->debug("Player %d will build %s in town of %s at %s",
|
logAi->debug("Player %d will build %s in town of %s at %s",
|
||||||
aiGw->playerID, town->getTown()->buildings.at(b)->getNameTranslated(), town->getNameTranslated(), town->anchorPos().toString());
|
aiGw->playerID, town->getTown()->buildings.at(b)->getNameTranslated(), town->getNameTranslated(), town->anchorPos().toString());
|
||||||
ccTl->buildBuilding(town, b);
|
aiGw->cc->buildBuilding(town, b);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ void BuyArmy::accept(AIGateway * aiGw)
|
|||||||
|
|
||||||
for(int i = 0; valueBought < value && i < armyToBuy.size(); i++)
|
for(int i = 0; valueBought < value && i < armyToBuy.size(); i++)
|
||||||
{
|
{
|
||||||
auto res = ccTl->getResourceAmount();
|
auto res = aiGw->cc->getResourceAmount();
|
||||||
auto & ci = armyToBuy[i];
|
auto & ci = armyToBuy[i];
|
||||||
|
|
||||||
if(objid != CreatureID::NONE && ci.creID.getNum() != objid)
|
if(objid != CreatureID::NONE && ci.creID.getNum() != objid)
|
||||||
@@ -81,12 +81,12 @@ void BuyArmy::accept(AIGateway * aiGw)
|
|||||||
}
|
}
|
||||||
if (lowestValueSlot.validSlot())
|
if (lowestValueSlot.validSlot())
|
||||||
{
|
{
|
||||||
ccTl->dismissCreature(town->getUpperArmy(), lowestValueSlot);
|
aiGw->cc->dismissCreature(town->getUpperArmy(), lowestValueSlot);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (town->getUpperArmy()->stacksCount() < GameConstants::ARMY_SIZE || town->getUpperArmy()->getSlotFor(ci.creID).validSlot()) //It is possible we don't scrap despite we wanted to due to not scrapping stacks that fit our faction
|
if (town->getUpperArmy()->stacksCount() < GameConstants::ARMY_SIZE || town->getUpperArmy()->getSlotFor(ci.creID).validSlot()) //It is possible we don't scrap despite we wanted to due to not scrapping stacks that fit our faction
|
||||||
{
|
{
|
||||||
ccTl->recruitCreatures(town, town->getUpperArmy(), ci.creID, ci.count, ci.level);
|
aiGw->cc->recruitCreatures(town, town->getUpperArmy(), ci.creID, ci.count, ci.level);
|
||||||
}
|
}
|
||||||
valueBought += ci.count * ci.creID.toCreature()->getAIValue();
|
valueBought += ci.count * ci.creID.toCreature()->getAIValue();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ using namespace Goals;
|
|||||||
|
|
||||||
bool isKeyMaster(const QuestInfo & q)
|
bool isKeyMaster(const QuestInfo & q)
|
||||||
{
|
{
|
||||||
auto object = q.getObject(ccTl);
|
const auto object = q.getObject(ccTl);
|
||||||
return object && (object->ID == Obj::BORDER_GATE || object->ID == Obj::BORDERGUARD);
|
return object && (object->ID == Obj::BORDER_GATE || object->ID == Obj::BORDERGUARD);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,7 +39,7 @@ TGoalVec CompleteQuest::decompose(const Nullkiller * aiNk) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
logAi->debug("Trying to realize quest: %s", questToString());
|
logAi->debug("Trying to realize quest: %s", questToString());
|
||||||
auto quest = q.getQuest(ccTl);
|
const auto quest = q.getQuest(aiNk->cc.get());
|
||||||
|
|
||||||
if(!quest->mission.artifacts.empty())
|
if(!quest->mission.artifacts.empty())
|
||||||
return missionArt(aiNk);
|
return missionArt(aiNk);
|
||||||
@@ -108,14 +108,14 @@ std::string CompleteQuest::questToString() const
|
|||||||
|
|
||||||
TGoalVec CompleteQuest::tryCompleteQuest(const Nullkiller * aiNk) const
|
TGoalVec CompleteQuest::tryCompleteQuest(const Nullkiller * aiNk) const
|
||||||
{
|
{
|
||||||
auto paths = aiNk->pathfinder->getPathInfo(q.getObject(ccTl)->visitablePos());
|
auto paths = aiNk->pathfinder->getPathInfo(q.getObject(aiNk->cc.get())->visitablePos());
|
||||||
|
|
||||||
vstd::erase_if(paths, [&](const AIPath & path) -> bool
|
vstd::erase_if(paths, [&](const AIPath & path) -> bool
|
||||||
{
|
{
|
||||||
return !q.getQuest(ccTl)->checkQuest(path.targetHero);
|
return !q.getQuest(aiNk->cc.get())->checkQuest(path.targetHero);
|
||||||
});
|
});
|
||||||
|
|
||||||
return CaptureObjectsBehavior::getVisitGoals(paths, aiNk, q.getObject(ccTl));
|
return CaptureObjectsBehavior::getVisitGoals(paths, aiNk, q.getObject(aiNk->cc.get()));
|
||||||
}
|
}
|
||||||
|
|
||||||
TGoalVec CompleteQuest::missionArt(const Nullkiller * aiNk) const
|
TGoalVec CompleteQuest::missionArt(const Nullkiller * aiNk) const
|
||||||
@@ -127,7 +127,7 @@ TGoalVec CompleteQuest::missionArt(const Nullkiller * aiNk) const
|
|||||||
|
|
||||||
CaptureObjectsBehavior findArts;
|
CaptureObjectsBehavior findArts;
|
||||||
|
|
||||||
for(auto art : q.getQuest(ccTl)->mission.artifacts)
|
for(auto art : q.getQuest(aiNk->cc.get())->mission.artifacts)
|
||||||
{
|
{
|
||||||
solutions.push_back(sptr(CaptureObjectsBehavior().ofType(Obj::ARTIFACT, art.getNum())));
|
solutions.push_back(sptr(CaptureObjectsBehavior().ofType(Obj::ARTIFACT, art.getNum())));
|
||||||
}
|
}
|
||||||
@@ -150,14 +150,14 @@ TGoalVec CompleteQuest::missionHero(const Nullkiller * aiNk) const
|
|||||||
|
|
||||||
TGoalVec CompleteQuest::missionArmy(const Nullkiller * aiNk) const
|
TGoalVec CompleteQuest::missionArmy(const Nullkiller * aiNk) const
|
||||||
{
|
{
|
||||||
auto paths = aiNk->pathfinder->getPathInfo(q.getObject(ccTl)->visitablePos());
|
auto paths = aiNk->pathfinder->getPathInfo(q.getObject(aiNk->cc.get())->visitablePos());
|
||||||
|
|
||||||
vstd::erase_if(paths, [&](const AIPath & path) -> bool
|
vstd::erase_if(paths, [&](const AIPath & path) -> bool
|
||||||
{
|
{
|
||||||
return !CQuest::checkMissionArmy(q.getQuest(ccTl), path.heroArmy);
|
return !CQuest::checkMissionArmy(q.getQuest(aiNk->cc.get()), path.heroArmy);
|
||||||
});
|
});
|
||||||
|
|
||||||
return CaptureObjectsBehavior::getVisitGoals(paths, aiNk, q.getObject(ccTl));
|
return CaptureObjectsBehavior::getVisitGoals(paths, aiNk, q.getObject(aiNk->cc.get()));
|
||||||
}
|
}
|
||||||
|
|
||||||
TGoalVec CompleteQuest::missionIncreasePrimaryStat(const Nullkiller * aiNk) const
|
TGoalVec CompleteQuest::missionIncreasePrimaryStat(const Nullkiller * aiNk) const
|
||||||
@@ -172,13 +172,13 @@ TGoalVec CompleteQuest::missionLevel(const Nullkiller * aiNk) const
|
|||||||
|
|
||||||
TGoalVec CompleteQuest::missionKeymaster(const Nullkiller * aiNk) const
|
TGoalVec CompleteQuest::missionKeymaster(const Nullkiller * aiNk) const
|
||||||
{
|
{
|
||||||
if(isObjectPassable(aiNk, q.getObject(ccTl)))
|
if(isObjectPassable(aiNk, q.getObject(aiNk->cc.get())))
|
||||||
{
|
{
|
||||||
return CaptureObjectsBehavior(q.getObject(ccTl)).decompose(aiNk);
|
return CaptureObjectsBehavior(q.getObject(aiNk->cc.get())).decompose(aiNk);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return CaptureObjectsBehavior().ofType(Obj::KEYMASTER, q.getObject(ccTl)->subID).decompose(aiNk);
|
return CaptureObjectsBehavior().ofType(Obj::KEYMASTER, q.getObject(aiNk->cc.get())->subID).decompose(aiNk);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -190,12 +190,11 @@ TGoalVec CompleteQuest::missionResources(const Nullkiller * aiNk) const
|
|||||||
|
|
||||||
TGoalVec CompleteQuest::missionDestroyObj(const Nullkiller * aiNk) const
|
TGoalVec CompleteQuest::missionDestroyObj(const Nullkiller * aiNk) const
|
||||||
{
|
{
|
||||||
auto obj = aiNk->cc->getObj(q.getQuest(ccTl)->killTarget);
|
const auto obj = aiNk->cc->getObj(q.getQuest(aiNk->cc.get())->killTarget);
|
||||||
|
|
||||||
if(!obj)
|
if(!obj)
|
||||||
return CaptureObjectsBehavior(q.getObject(ccTl)).decompose(aiNk);
|
return CaptureObjectsBehavior(q.getObject(aiNk->cc.get())).decompose(aiNk);
|
||||||
|
|
||||||
auto relations = aiNk->cc->getPlayerRelations(aiNk->playerID, obj->tempOwner);
|
const auto relations = aiNk->cc->getPlayerRelations(aiNk->playerID, obj->tempOwner);
|
||||||
|
|
||||||
//if(relations == PlayerRelations::SAME_PLAYER)
|
//if(relations == PlayerRelations::SAME_PLAYER)
|
||||||
//{
|
//{
|
||||||
|
|||||||
@@ -26,8 +26,7 @@ void DismissHero::accept(AIGateway * aiGw)
|
|||||||
if(!hero)
|
if(!hero)
|
||||||
throw cannotFulfillGoalException("Invalid hero!");
|
throw cannotFulfillGoalException("Invalid hero!");
|
||||||
|
|
||||||
ccTl->dismissHero(hero);
|
aiGw->cc->dismissHero(hero);
|
||||||
|
|
||||||
throw goalFulfilledException(sptr(*this));
|
throw goalFulfilledException(sptr(*this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ void ExchangeSwapTownHeroes::accept(AIGateway * aiGw)
|
|||||||
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.");
|
||||||
|
|
||||||
ccTl->swapGarrisonHero(town);
|
aiGw->cc->swapGarrisonHero(town);
|
||||||
|
|
||||||
if(currentGarrisonHero != town->getVisitingHero())
|
if(currentGarrisonHero != town->getVisitingHero())
|
||||||
{
|
{
|
||||||
@@ -81,7 +81,7 @@ void ExchangeSwapTownHeroes::accept(AIGateway * aiGw)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(town->getVisitingHero() && town->getVisitingHero() != getGarrisonHero())
|
if(town->getVisitingHero() && town->getVisitingHero() != getGarrisonHero())
|
||||||
ccTl->swapGarrisonHero(town);
|
aiGw->cc->swapGarrisonHero(town);
|
||||||
|
|
||||||
aiGw->makePossibleUpgrades(town);
|
aiGw->makePossibleUpgrades(town);
|
||||||
aiGw->moveHeroToTile(town->visitablePos(), HeroPtr(getGarrisonHero(), aiGw->cc));
|
aiGw->moveHeroToTile(town->visitablePos(), HeroPtr(getGarrisonHero(), aiGw->cc));
|
||||||
@@ -94,12 +94,12 @@ void ExchangeSwapTownHeroes::accept(AIGateway * aiGw)
|
|||||||
{
|
{
|
||||||
while (upperArmy->stacksCount() != 0)
|
while (upperArmy->stacksCount() != 0)
|
||||||
{
|
{
|
||||||
ccTl->dismissCreature(upperArmy, upperArmy->Slots().begin()->first);
|
aiGw->cc->dismissCreature(upperArmy, upperArmy->Slots().begin()->first);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ccTl->swapGarrisonHero(town);
|
aiGw->cc->swapGarrisonHero(town);
|
||||||
|
|
||||||
if(lockingReason != HeroLockedReason::NOT_LOCKED)
|
if(lockingReason != HeroLockedReason::NOT_LOCKED)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -38,15 +38,13 @@ void RecruitHero::accept(AIGateway * aiGw)
|
|||||||
|
|
||||||
logAi->debug("Trying to recruit a hero in %s at %s", t->getNameTranslated(), t->visitablePos().toString());
|
logAi->debug("Trying to recruit a hero in %s at %s", t->getNameTranslated(), t->visitablePos().toString());
|
||||||
|
|
||||||
auto heroes = ccTl->getAvailableHeroes(t);
|
const auto heroes = aiGw->cc->getAvailableHeroes(t);
|
||||||
|
|
||||||
if(!heroes.size())
|
if(!heroes.size())
|
||||||
{
|
{
|
||||||
throw cannotFulfillGoalException("No available heroes in tavern in " + t->nodeName());
|
throw cannotFulfillGoalException("No available heroes in tavern in " + t->nodeName());
|
||||||
}
|
}
|
||||||
|
|
||||||
auto heroToHire = heroToBuy;
|
auto heroToHire = heroToBuy;
|
||||||
|
|
||||||
if(!heroToHire)
|
if(!heroToHire)
|
||||||
{
|
{
|
||||||
for(auto hero : heroes)
|
for(auto hero : heroes)
|
||||||
@@ -61,13 +59,13 @@ void RecruitHero::accept(AIGateway * aiGw)
|
|||||||
|
|
||||||
if(t->getVisitingHero())
|
if(t->getVisitingHero())
|
||||||
{
|
{
|
||||||
ccTl->swapGarrisonHero(t);
|
aiGw->cc->swapGarrisonHero(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(t->getVisitingHero())
|
if(t->getVisitingHero())
|
||||||
throw cannotFulfillGoalException("Town " + t->nodeName() + " is occupied. Cannot recruit hero!");
|
throw cannotFulfillGoalException("Town " + t->nodeName() + " is occupied. Cannot recruit hero!");
|
||||||
|
|
||||||
ccTl->recruitHero(t, heroToHire);
|
aiGw->cc->recruitHero(t, heroToHire);
|
||||||
|
|
||||||
{
|
{
|
||||||
// TODO: Mircea: Consider same behavior when a hero is lost? Relevant?
|
// TODO: Mircea: Consider same behavior when a hero is lost? Relevant?
|
||||||
|
|||||||
@@ -86,8 +86,7 @@ void ObjectGraph::removeObject(const CGObjectInstance * obj)
|
|||||||
{
|
{
|
||||||
vstd::erase_if(nodes[obj->visitablePos()].connections, [&](const std::pair<int3, ObjectLink> & link) -> bool
|
vstd::erase_if(nodes[obj->visitablePos()].connections, [&](const std::pair<int3, ObjectLink> & link) -> bool
|
||||||
{
|
{
|
||||||
auto tile = ccTl->getTile(link.first, false);
|
const auto tile = ccTl->getTile(link.first, false);
|
||||||
|
|
||||||
return tile && tile->isWater();
|
return tile && tile->isWater();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -205,12 +205,12 @@ void ObjectGraphCalculator::calculateConnections(const int3 & pos, std::vector<A
|
|||||||
auto obj1 = actorObjectMap[path1.targetHero];
|
auto obj1 = actorObjectMap[path1.targetHero];
|
||||||
auto obj2 = actorObjectMap[path2.targetHero];
|
auto obj2 = actorObjectMap[path2.targetHero];
|
||||||
|
|
||||||
auto tile1 = ccTl->getTile(pos1);
|
auto tile1 = aiNk->cc->getTile(pos1);
|
||||||
auto tile2 = ccTl->getTile(pos2);
|
auto tile2 = aiNk->cc->getTile(pos2);
|
||||||
|
|
||||||
if(tile2->isWater() && !tile1->isWater())
|
if(tile2->isWater() && !tile1->isWater())
|
||||||
{
|
{
|
||||||
if(!ccTl->getTile(pos)->isWater())
|
if(!aiNk->cc->getTile(pos)->isWater())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
auto startingObjIsBoat = (obj1 && obj1->ID == Obj::BOAT) || target->isVirtualBoat(pos1);
|
auto startingObjIsBoat = (obj1 && obj1->ID == Obj::BOAT) || target->isVirtualBoat(pos1);
|
||||||
@@ -295,7 +295,7 @@ void ObjectGraphCalculator::addObjectActor(const CGObjectInstance * obj)
|
|||||||
objectActor->pos = objectActor->convertFromVisitablePos(visitablePos);
|
objectActor->pos = objectActor->convertFromVisitablePos(visitablePos);
|
||||||
objectActor->initObj(randomizer);
|
objectActor->initObj(randomizer);
|
||||||
|
|
||||||
if(ccTl->getTile(visitablePos)->isWater())
|
if(aiNk->cc->getTile(visitablePos)->isWater())
|
||||||
{
|
{
|
||||||
objectActor->setBoat(temporaryBoats.emplace_back(std::make_unique<CGBoat>(objectActor->cb)).get());
|
objectActor->setBoat(temporaryBoats.emplace_back(std::make_unique<CGBoat>(objectActor->cb)).get());
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user