1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-11-23 22:37:55 +02:00

consistent renaming of ai into aiGw or aiNk and cbc

This commit is contained in:
Mircea TheHonestCTO
2025-08-16 00:22:18 +02:00
parent 6b6298fa33
commit b8bf8714a1
25 changed files with 85 additions and 85 deletions

View File

@@ -40,26 +40,26 @@ namespace NK2AI
{
//one thread may be turn of AI and another will be handling a side effect for AI2
thread_local CCallback * cbc = nullptr;
thread_local AIGateway * aiGw = nullptr;
thread_local CCallback * cbcTl = nullptr;
thread_local AIGateway * aiGwTl = nullptr;
//helper RAII to manage global ai/cb ptrs
struct SetGlobalState
{
SetGlobalState(AIGateway * gateway)
{
assert(!aiGw);
assert(!cbc);
assert(!aiGwTl);
assert(!cbcTl);
aiGw = gateway;
cbc = gateway->cbc.get();
aiGwTl = gateway;
cbcTl = gateway->cbc.get();
}
~SetGlobalState()
{
//TODO: how to handle rm? shouldn't be called after ai is destroyed, hopefully
//TODO: to ensure that, make rm unique_ptr
aiGw = nullptr;
cbc = nullptr;
aiGwTl = nullptr;
cbcTl = nullptr;
}
};
@@ -1337,7 +1337,7 @@ bool AIGateway::moveHeroToTile(int3 dst, HeroPtr h)
void AIGateway::buildStructure(const CGTownInstance * t, BuildingID building)
{
auto name = t->getTown()->buildings.at(building)->getNameTranslated();
logAi->debug("Player %d will build %s in town of %s at %s", aiGw->playerID, name, t->getNameTranslated(), t->anchorPos().toString());
logAi->debug("Player %d will build %s in town of %s at %s", aiGwTl->playerID, name, t->getNameTranslated(), t->anchorPos().toString());
cbc->buildBuilding(t, building); //just do this;
}

View File

@@ -30,17 +30,17 @@ namespace NK2AI
const CGObjectInstance * ObjectIdRef::operator->() const
{
return cbc->getObj(id, false);
return cbcTl->getObj(id, false);
}
ObjectIdRef::operator const CGObjectInstance *() const
{
return cbc->getObj(id, false);
return cbcTl->getObj(id, false);
}
ObjectIdRef::operator bool() const
{
return cbc->getObj(id, false);
return cbcTl->getObj(id, false);
}
ObjectIdRef::ObjectIdRef(ObjectInstanceID _id)
@@ -101,7 +101,7 @@ std::string HeroPtr::name() const
const CGHeroInstance * HeroPtr::get(bool doWeExpectNull) const
{
return get(cbc, doWeExpectNull);
return get(cbcTl, doWeExpectNull);
}
const CGHeroInstance * HeroPtr::get(const CPlayerSpecificInfoCallback * cb, bool doWeExpectNull) const
@@ -203,7 +203,7 @@ bool canBeEmbarkmentPoint(const TerrainTile * t, bool fromWater)
}
else if(!fromWater) // do not try to board when in water sector
{
if(t->visitableObjects.size() == 1 && cbc->getObjInstance(t->topVisitableObj())->ID == Obj::BOAT)
if(t->visitableObjects.size() == 1 && cbcTl->getObjInstance(t->topVisitableObj())->ID == Obj::BOAT)
return true;
}
return false;
@@ -234,7 +234,7 @@ bool isObjectPassable(const CGObjectInstance * obj, PlayerColor playerColor, Pla
bool isBlockVisitObj(const int3 & pos)
{
if(auto obj = cbc->getTopObj(pos))
if(auto obj = cbcTl->getTopObj(pos))
{
if(obj->isBlockedVisitable()) //we can't stand on that object
return true;

View File

@@ -62,7 +62,7 @@ const int WOOD_ORE_MINE_PRODUCTION = 2;
const int RESOURCE_MINE_PRODUCTION = 1;
const int ACTUAL_RESOURCE_COUNT = 7;
extern thread_local CCallback * cbc;
extern thread_local CCallback * cbcTl;
enum HeroRole
{
@@ -148,7 +148,7 @@ void foreach_tile_pos(const Func & foo)
{
// some micro-optimizations since this function gets called a LOT
// callback pointer is thread-specific and slow to retrieve -> read map size only once
int3 mapSize = cbc->getMapSize();
int3 mapSize = cbcTl->getMapSize();
for(int z = 0; z < mapSize.z; z++)
{
for(int x = 0; x < mapSize.x; x++)
@@ -180,7 +180,7 @@ void foreach_tile_pos(TCallback * cbp, const Func & foo) // avoid costly retriev
template<class Func>
void foreach_neighbour(const int3 & pos, const Func & foo)
{
CCallback * cbp = cbc; // avoid costly retrieval of thread-specific pointer
CCallback * cbp = cbcTl; // avoid costly retrieval of thread-specific pointer
for(const int3 & dir : int3::getDirs())
{
const int3 n = pos + dir;

View File

@@ -50,7 +50,7 @@ void BuildAnalyzer::update()
for(const CGTownInstance* town : towns)
{
if(town->built >= cbc->getSettings().getInteger(EGameSettings::TOWNS_BUILDINGS_PER_TURN_CAP))
if(town->built >= cbcTl->getSettings().getInteger(EGameSettings::TOWNS_BUILDINGS_PER_TURN_CAP))
continue; // Not much point in trying anything - can't built in this town anymore today
#if NKAI_TRACE_LEVEL >= 1

View File

@@ -310,7 +310,7 @@ void ObjectClusterizer::clusterize()
{
for(auto id : invalidated)
{
auto obj = cbc->getObj(id, false);
auto obj = cbcTl->getObj(id, false);
if(obj)
{
@@ -354,7 +354,7 @@ void ObjectClusterizer::clusterize()
for(auto pair : blockedObjects)
{
auto blocker = cbc->getObj(pair.first);
auto blocker = cbcTl->getObj(pair.first);
logAi->trace("Cluster %s %s count: %i", blocker->getObjectName(), blocker->visitablePos().toString(), pair.second->objects.size());

View File

@@ -28,7 +28,7 @@ Goals::TGoalVec BuyArmyBehavior::decompose(const Nullkiller * aiNk) const
{
Goals::TGoalVec tasks;
auto heroes = cbc->getHeroesInfo();
auto heroes = cbcTl->getHeroesInfo();
if(heroes.empty())
{
@@ -37,11 +37,11 @@ Goals::TGoalVec BuyArmyBehavior::decompose(const Nullkiller * aiNk) const
aiNk->dangerHitMap->updateHitMap();
for(auto town : cbc->getTownsInfo())
for(auto town : cbcTl->getTownsInfo())
{
uint8_t closestThreat = aiNk->dangerHitMap->getTileThreat(town->visitablePos()).fastestDanger.turn;
if (closestThreat >=2 && aiNk->buildAnalyzer->isGoldPressureOverMax() && !town->hasBuilt(BuildingID::CITY_HALL) && cbc->canBuildStructure(town, BuildingID::CITY_HALL) != EBuildingState::FORBIDDEN)
if (closestThreat >=2 && aiNk->buildAnalyzer->isGoldPressureOverMax() && !town->hasBuilt(BuildingID::CITY_HALL) && cbcTl->canBuildStructure(town, BuildingID::CITY_HALL) != EBuildingState::FORBIDDEN)
{
return tasks;
}

View File

@@ -51,11 +51,11 @@ Goals::TGoalVec ExplorationBehavior::decompose(const Nullkiller * aiNk) const
case Obj::WHIRLPOOL:
{
auto tObj = dynamic_cast<const CGTeleport*>(obj);
for (auto exit : cbc->getTeleportChannelExits(tObj->channel))
for (auto exit : cbcTl->getTeleportChannelExits(tObj->channel))
{
if (exit != tObj->id)
{
if (!cbc->isVisible(cbc->getObjInstance(exit)))
if (!cbcTl->isVisible(cbcTl->getObjInstance(exit)))
tasks.push_back(sptr(Composition().addNext(ExplorationPoint(obj->visitablePos(), 50)).addNext(CaptureObject(obj))));
}
}

View File

@@ -314,7 +314,7 @@ Goals::TGoalVec GatherArmyBehavior::upgradeArmy(const Nullkiller * aiNk, const C
&& aiNk->heroManager->canRecruitHero(upgrader)
&& path.turn() < aiNk->settings->getScoutHeroTurnDistanceLimit())
{
for(auto hero : cbc->getAvailableHeroes(upgrader))
for(auto hero : cbcTl->getAvailableHeroes(upgrader))
{
auto scoutReinforcement = aiNk->armyManager->howManyReinforcementsCanGet(hero, upgrader);

View File

@@ -97,15 +97,15 @@ bool needToRecruitHero(const Nullkiller * aiNk, const CGTownInstance * startupTo
}
}
auto basicCount = cbc->getTownsInfo().size() + 2;
auto basicCount = cbcTl->getTownsInfo().size() + 2;
auto boost = std::min(
(int)std::floor(std::pow(1 + (cbc->getMapSize().x / 50), 2)),
(int)std::floor(std::pow(1 + (cbcTl->getMapSize().x / 50), 2)),
treasureSourcesCount / 2);
logAi->trace("Treasure sources found %d", treasureSourcesCount);
logAi->trace("Startup allows %d+%d heroes", basicCount, boost);
return cbc->getHeroCount(aiNk->playerID, true) < basicCount + boost;
return cbcTl->getHeroCount(aiNk->playerID, true) < basicCount + boost;
}
Goals::TGoalVec StartupBehavior::decompose(const Nullkiller * aiNk) const

View File

@@ -146,8 +146,8 @@ bool isEquivalentGoals(TSubgoal goal1, TSubgoal goal2)
if(goal1->goalType == Goals::CAPTURE_OBJECT && goal2->goalType == Goals::CAPTURE_OBJECT)
{
auto o1 = cbc->getObj(ObjectInstanceID(goal1->objid));
auto o2 = cbc->getObj(ObjectInstanceID(goal2->objid));
auto o1 = cbcTl->getObj(ObjectInstanceID(goal1->objid));
auto o2 = cbcTl->getObj(ObjectInstanceID(goal2->objid));
return o1->ID == Obj::SHIPYARD && o1->ID == o2->ID;
}

View File

@@ -595,7 +595,7 @@ float RewardEvaluator::evaluateWitchHutSkillScore(const CGObjectInstance * hut,
return role == HeroRole::SCOUT ? 2 : 0;
if(hero->getSecSkillLevel(skill) != MasteryLevel::NONE
|| static_cast<int>(hero->secSkills.size()) >= cbc->getSettings().getInteger(EGameSettings::HEROES_SKILL_PER_HERO))
|| static_cast<int>(hero->secSkills.size()) >= cbcTl->getSettings().getInteger(EGameSettings::HEROES_SKILL_PER_HERO))
return 0;
auto score = aiNk->heroManager->evaluateSecSkill(skill, hero);

View File

@@ -47,7 +47,7 @@ std::string AbstractGoal::toString() const
break;
case TRADE:
{
auto obj = cbc->getObjInstance(ObjectInstanceID(objid));
auto obj = cbcTl->getObjInstance(ObjectInstanceID(objid));
if (obj)
desc = (boost::format("TRADE %d of %s at %s") % value % GameConstants::RESOURCE_NAMES[resID] % obj->getObjectName()).str();
}

View File

@@ -59,10 +59,10 @@ void AdventureSpellCast::accept(AIGateway * aiGw)
if (hero->isGarrisoned())
aiGw->cbc->swapGarrisonHero(hero->getVisitedTown());
auto wait = cbc->waitTillRealize;
auto wait = cbcTl->waitTillRealize;
cbc->waitTillRealize = true;
cbc->castSpell(hero, spellID, tile);
cbcTl->waitTillRealize = true;
cbcTl->castSpell(hero, spellID, tile);
if(town && townPortalEffect)
{
@@ -70,7 +70,7 @@ void AdventureSpellCast::accept(AIGateway * aiGw)
aiGw->moveHeroToTile(town->visitablePos(), hero);
}
cbc->waitTillRealize = wait;
cbcTl->waitTillRealize = wait;
throw goalFulfilledException(sptr(*this));
}

View File

@@ -23,8 +23,8 @@
namespace Nullkiller
{
extern boost::thread_specific_ptr<CCallback> cbc;
extern boost::thread_specific_ptr<AIGateway> aiGw;
extern thread_local CCallback * cbc;
extern thread_local AIGateway * aiGw;
extern FuzzyHelper * fh;
using namespace Goals;

View File

@@ -45,12 +45,12 @@ void BuildBoat::accept(AIGateway * aiGw)
TResources boatCost;
shipyard->getBoatCost(boatCost);
if(!cbc->getResourceAmount().canAfford(boatCost))
if(!cbcTl->getResourceAmount().canAfford(boatCost))
{
throw cannotFulfillGoalException("Can not afford boat");
}
if(cbc->getPlayerRelations(aiGw->playerID, shipyard->getObject()->getOwner()) == PlayerRelations::ENEMIES)
if(cbcTl->getPlayerRelations(aiGw->playerID, shipyard->getObject()->getOwner()) == PlayerRelations::ENEMIES)
{
throw cannotFulfillGoalException("Can not build boat in enemy shipyard");
}
@@ -65,7 +65,7 @@ void BuildBoat::accept(AIGateway * aiGw)
shipyard->getObject()->visitablePos().toString(),
shipyard->bestLocation().toString());
cbc->buildBoat(shipyard);
cbcTl->buildBoat(shipyard);
throw goalFulfilledException(sptr(*this));
}

View File

@@ -52,11 +52,11 @@ void BuildThis::accept(AIGateway * aiGw)
if(town)
{
if(cbc->canBuildStructure(town, b) == EBuildingState::ALLOWED)
if(cbcTl->canBuildStructure(town, b) == EBuildingState::ALLOWED)
{
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());
cbc->buildBuilding(town, b);
cbcTl->buildBuilding(town, b);
return;
}

View File

@@ -48,7 +48,7 @@ void BuyArmy::accept(AIGateway * aiGw)
for(int i = 0; valueBought < value && i < armyToBuy.size(); i++)
{
auto res = cbc->getResourceAmount();
auto res = cbcTl->getResourceAmount();
auto & ci = armyToBuy[i];
if(objid != CreatureID::NONE && ci.creID.getNum() != objid)
@@ -81,12 +81,12 @@ void BuyArmy::accept(AIGateway * aiGw)
}
if (lowestValueSlot.validSlot())
{
cbc->dismissCreature(town->getUpperArmy(), lowestValueSlot);
cbcTl->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
{
cbc->recruitCreatures(town, town->getUpperArmy(), ci.creID, ci.count, ci.level);
cbcTl->recruitCreatures(town, town->getUpperArmy(), ci.creID, ci.count, ci.level);
}
valueBought += ci.count * ci.creID.toCreature()->getAIValue();
}

View File

@@ -22,7 +22,7 @@ using namespace Goals;
bool isKeyMaster(const QuestInfo & q)
{
auto object = q.getObject(cbc);
auto object = q.getObject(cbcTl);
return object && (object->ID == Obj::BORDER_GATE || object->ID == Obj::BORDERGUARD);
}
@@ -39,7 +39,7 @@ TGoalVec CompleteQuest::decompose(const Nullkiller * ai) const
}
logAi->debug("Trying to realize quest: %s", questToString());
auto quest = q.getQuest(cbc);
auto quest = q.getQuest(cbcTl);
if(!quest->mission.artifacts.empty())
return missionArt(ai);
@@ -70,52 +70,52 @@ bool CompleteQuest::operator==(const CompleteQuest & other) const
{
if(isKeyMaster(q))
{
return isKeyMaster(other.q) && q.getObject(cbc)->subID == other.q.getObject(cbc)->subID;
return isKeyMaster(other.q) && q.getObject(cbcTl)->subID == other.q.getObject(cbcTl)->subID;
}
else if(isKeyMaster(other.q))
{
return false;
}
return q.getQuest(cbc) == other.q.getQuest(cbc);
return q.getQuest(cbcTl) == other.q.getQuest(cbcTl);
}
uint64_t CompleteQuest::getHash() const
{
if(isKeyMaster(q))
{
return q.getObject(cbc)->subID;
return q.getObject(cbcTl)->subID;
}
return q.getObject(cbc)->id.getNum();
return q.getObject(cbcTl)->id.getNum();
}
std::string CompleteQuest::questToString() const
{
if(isKeyMaster(q))
{
return "find " + LIBRARY->generaltexth->tentColors[q.getObject(cbc)->subID] + " keymaster tent";
return "find " + LIBRARY->generaltexth->tentColors[q.getObject(cbcTl)->subID] + " keymaster tent";
}
if(q.getQuest(cbc)->questName == CQuest::missionName(EQuestMission::NONE))
if(q.getQuest(cbcTl)->questName == CQuest::missionName(EQuestMission::NONE))
return "inactive quest";
MetaString ms;
q.getQuest(cbc)->getRolloverText(cbc, ms, false);
q.getQuest(cbcTl)->getRolloverText(cbcTl, ms, false);
return ms.toString();
}
TGoalVec CompleteQuest::tryCompleteQuest(const Nullkiller * aiNk) const
{
auto paths = aiNk->pathfinder->getPathInfo(q.getObject(cbc)->visitablePos());
auto paths = aiNk->pathfinder->getPathInfo(q.getObject(cbcTl)->visitablePos());
vstd::erase_if(paths, [&](const AIPath & path) -> bool
{
return !q.getQuest(cbc)->checkQuest(path.targetHero);
return !q.getQuest(cbcTl)->checkQuest(path.targetHero);
});
return CaptureObjectsBehavior::getVisitGoals(paths, aiNk, q.getObject(cbc));
return CaptureObjectsBehavior::getVisitGoals(paths, aiNk, q.getObject(cbcTl));
}
TGoalVec CompleteQuest::missionArt(const Nullkiller * ai) const
@@ -127,7 +127,7 @@ TGoalVec CompleteQuest::missionArt(const Nullkiller * ai) const
CaptureObjectsBehavior findArts;
for(auto art : q.getQuest(cbc)->mission.artifacts)
for(auto art : q.getQuest(cbcTl)->mission.artifacts)
{
solutions.push_back(sptr(CaptureObjectsBehavior().ofType(Obj::ARTIFACT, art.getNum())));
}
@@ -150,14 +150,14 @@ TGoalVec CompleteQuest::missionHero(const Nullkiller * ai) const
TGoalVec CompleteQuest::missionArmy(const Nullkiller * aiNk) const
{
auto paths = aiNk->pathfinder->getPathInfo(q.getObject(cbc)->visitablePos());
auto paths = aiNk->pathfinder->getPathInfo(q.getObject(cbcTl)->visitablePos());
vstd::erase_if(paths, [&](const AIPath & path) -> bool
{
return !CQuest::checkMissionArmy(q.getQuest(cbc), path.heroArmy);
return !CQuest::checkMissionArmy(q.getQuest(cbcTl), path.heroArmy);
});
return CaptureObjectsBehavior::getVisitGoals(paths, aiNk, q.getObject(cbc));
return CaptureObjectsBehavior::getVisitGoals(paths, aiNk, q.getObject(cbcTl));
}
TGoalVec CompleteQuest::missionIncreasePrimaryStat(const Nullkiller * ai) const
@@ -172,13 +172,13 @@ TGoalVec CompleteQuest::missionLevel(const Nullkiller * ai) const
TGoalVec CompleteQuest::missionKeymaster(const Nullkiller * ai) const
{
if(isObjectPassable(ai, q.getObject(cbc)))
if(isObjectPassable(ai, q.getObject(cbcTl)))
{
return CaptureObjectsBehavior(q.getObject(cbc)).decompose(ai);
return CaptureObjectsBehavior(q.getObject(cbcTl)).decompose(ai);
}
else
{
return CaptureObjectsBehavior().ofType(Obj::KEYMASTER, q.getObject(cbc)->subID).decompose(ai);
return CaptureObjectsBehavior().ofType(Obj::KEYMASTER, q.getObject(cbcTl)->subID).decompose(ai);
}
}
@@ -190,10 +190,10 @@ TGoalVec CompleteQuest::missionResources(const Nullkiller * ai) const
TGoalVec CompleteQuest::missionDestroyObj(const Nullkiller * aiNk) const
{
auto obj = aiNk->cbc->getObj(q.getQuest(cbc)->killTarget);
auto obj = aiNk->cbc->getObj(q.getQuest(cbcTl)->killTarget);
if(!obj)
return CaptureObjectsBehavior(q.getObject(cbc)).decompose(aiNk);
return CaptureObjectsBehavior(q.getObject(cbcTl)).decompose(aiNk);
auto relations = aiNk->cbc->getPlayerRelations(aiNk->playerID, obj->tempOwner);

View File

@@ -26,7 +26,7 @@ void DismissHero::accept(AIGateway * aiGw)
if(!hero)
throw cannotFulfillGoalException("Invalid hero!");
cbc->dismissHero(hero);
cbcTl->dismissHero(hero);
throw goalFulfilledException(sptr(*this));
}

View File

@@ -65,7 +65,7 @@ void ExchangeSwapTownHeroes::accept(AIGateway * aiGw)
if(!currentGarrisonHero)
throw cannotFulfillGoalException("Invalid configuration. There is no hero in town garrison.");
cbc->swapGarrisonHero(town);
cbcTl->swapGarrisonHero(town);
if(currentGarrisonHero != town->getVisitingHero())
{
@@ -81,7 +81,7 @@ void ExchangeSwapTownHeroes::accept(AIGateway * aiGw)
}
if(town->getVisitingHero() && town->getVisitingHero() != getGarrisonHero())
cbc->swapGarrisonHero(town);
cbcTl->swapGarrisonHero(town);
aiGw->makePossibleUpgrades(town);
aiGw->moveHeroToTile(town->visitablePos(), getGarrisonHero());
@@ -94,12 +94,12 @@ void ExchangeSwapTownHeroes::accept(AIGateway * aiGw)
{
while (upperArmy->stacksCount() != 0)
{
cbc->dismissCreature(upperArmy, upperArmy->Slots().begin()->first);
cbcTl->dismissCreature(upperArmy, upperArmy->Slots().begin()->first);
}
}
}
cbc->swapGarrisonHero(town);
cbcTl->swapGarrisonHero(town);
if(lockingReason != HeroLockedReason::NOT_LOCKED)
{

View File

@@ -22,8 +22,8 @@
namespace Nullkiller
{
extern boost::thread_specific_ptr<CCallback> cbc;
extern boost::thread_specific_ptr<AIGateway> aiGw;
extern thread_local CCallback * cbc;
extern thread_local AIGateway * aiGw;
extern FuzzyHelper * fh;
using namespace Goals;

View File

@@ -38,7 +38,7 @@ void RecruitHero::accept(AIGateway * aiGw)
logAi->debug("Trying to recruit a hero in %s at %s", t->getNameTranslated(), t->visitablePos().toString());
auto heroes = cbc->getAvailableHeroes(t);
auto heroes = cbcTl->getAvailableHeroes(t);
if(!heroes.size())
{
@@ -61,13 +61,13 @@ void RecruitHero::accept(AIGateway * aiGw)
if(t->getVisitingHero())
{
cbc->swapGarrisonHero(t);
cbcTl->swapGarrisonHero(t);
}
if(t->getVisitingHero())
throw cannotFulfillGoalException("Town " + t->nodeName() + " is occupied. Cannot recruit hero!");
cbc->recruitHero(t, heroToHire);
cbcTl->recruitHero(t, heroToHire);
{
std::unique_lock lockGuard(aiGw->nullkiller->aiStateMutex);

View File

@@ -86,7 +86,7 @@ void ObjectGraph::removeObject(const CGObjectInstance * obj)
{
vstd::erase_if(nodes[obj->visitablePos()].connections, [&](const std::pair<int3, ObjectLink> & link) -> bool
{
auto tile = cbc->getTile(link.first, false);
auto tile = cbcTl->getTile(link.first, false);
return tile && tile->isWater();
});

View File

@@ -205,12 +205,12 @@ void ObjectGraphCalculator::calculateConnections(const int3 & pos, std::vector<A
auto obj1 = actorObjectMap[path1.targetHero];
auto obj2 = actorObjectMap[path2.targetHero];
auto tile1 = cbc->getTile(pos1);
auto tile2 = cbc->getTile(pos2);
auto tile1 = cbcTl->getTile(pos1);
auto tile2 = cbcTl->getTile(pos2);
if(tile2->isWater() && !tile1->isWater())
{
if(!cbc->getTile(pos)->isWater())
if(!cbcTl->getTile(pos)->isWater())
continue;
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->initObj(randomizer);
if(cbc->getTile(visitablePos)->isWater())
if(cbcTl->getTile(visitablePos)->isWater())
{
objectActor->setBoat(temporaryBoats.emplace_back(std::make_unique<CGBoat>(objectActor->cb)).get());
}

View File

@@ -49,7 +49,7 @@ namespace AIPathfinding
return;
// when actor represents moster graph node, we need to let him escape monster
if(cbc->getGuardingCreaturePosition(source.coord) == actor->initialPosition)
if(cbcTl->getGuardingCreaturePosition(source.coord) == actor->initialPosition)
return;
}