1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-10-31 00:07:39 +02:00

Nullkiller: various fixes for town portal and other

This commit is contained in:
Andrii Danylchenko
2021-05-16 14:45:30 +03:00
committed by Andrii Danylchenko
parent 1a69a43f09
commit e95ccda5de
9 changed files with 59 additions and 26 deletions

View File

@@ -258,6 +258,29 @@ bool canBeEmbarkmentPoint(const TerrainTile * t, bool fromWater)
return false; return false;
} }
bool isObjectPassable(const CGObjectInstance * obj)
{
return isObjectPassable(obj, ai->playerID, cb->getPlayerRelations(obj->tempOwner, ai->playerID));
}
// Pathfinder internal helper
bool isObjectPassable(const CGObjectInstance * obj, PlayerColor playerColor, PlayerRelations::PlayerRelations objectRelations)
{
if((obj->ID == Obj::GARRISON || obj->ID == Obj::GARRISON2)
&& objectRelations != PlayerRelations::ENEMIES)
return true;
if(obj->ID == Obj::BORDER_GATE)
{
auto quest = dynamic_cast<const CGKeys *>(obj);
if(quest->passableFor(playerColor))
return true;
}
return false;
}
bool isBlockedBorderGate(int3 tileToHit) //TODO: is that function needed? should be handled by pathfinder bool isBlockedBorderGate(int3 tileToHit) //TODO: is that function needed? should be handled by pathfinder
{ {
if(cb->getTile(tileToHit)->topVisitableId() != Obj::BORDER_GATE) if(cb->getTile(tileToHit)->topVisitableId() != Obj::BORDER_GATE)

View File

@@ -167,7 +167,9 @@ void foreach_neighbour(const int3 & pos, std::function<void(const int3 & pos)> f
void foreach_neighbour(CCallback * cbp, const int3 & pos, std::function<void(CCallback * cbp, const int3 & pos)> foo); // avoid costly retrieval of thread-specific pointer void foreach_neighbour(CCallback * cbp, const int3 & pos, std::function<void(CCallback * cbp, const int3 & pos)> foo); // avoid costly retrieval of thread-specific pointer
bool canBeEmbarkmentPoint(const TerrainTile * t, bool fromWater); bool canBeEmbarkmentPoint(const TerrainTile * t, bool fromWater);
bool isBlockedBorderGate(int3 tileToHit); //bool isBlockedBorderGate(int3 tileToHit);
bool isObjectPassable(const CGObjectInstance * obj);
bool isObjectPassable(const CGObjectInstance * obj, PlayerColor playerColor, PlayerRelations::PlayerRelations objectRelations);
bool isBlockVisitObj(const int3 & pos); bool isBlockVisitObj(const int3 & pos);
bool isWeeklyRevisitable(const CGObjectInstance * obj); bool isWeeklyRevisitable(const CGObjectInstance * obj);

View File

@@ -113,7 +113,8 @@ const CGObjectInstance * ObjectClusterizer::getBlocker(const AIPath & path) cons
|| blocker->ID == Obj::QUEST_GUARD || blocker->ID == Obj::QUEST_GUARD
|| blocker->ID == Obj::BORDER_GATE) || blocker->ID == Obj::BORDER_GATE)
{ {
return blocker; if(!isObjectPassable(blocker))
return blocker;
} }
} }

View File

@@ -82,7 +82,7 @@ Goals::TGoalVec ClusterBehavior::decomposeCluster(std::shared_ptr<ObjectCluster>
{ {
blockerPaths.back().nodes.insert(blockerPaths.back().nodes.begin(), *node); blockerPaths.back().nodes.insert(blockerPaths.back().nodes.begin(), *node);
if(node->coord == blockerPos) if(node->coord == blockerPos || cb->getGuardingCreaturePosition(node->coord) == blockerPos)
break; break;
} }

View File

@@ -19,6 +19,9 @@
#include "../../../lib/PathfinderUtil.h" #include "../../../lib/PathfinderUtil.h"
#include "../../../lib/CPlayerState.h" #include "../../../lib/CPlayerState.h"
/// 1-3 - position on map, 4 - layer (air, water, land), 5 - chain (normal, battle, spellcast and combinations)
boost::multi_array<AIPathNode, 5> nodes;
AINodeStorage::AINodeStorage(const int3 & Sizes) AINodeStorage::AINodeStorage(const int3 & Sizes)
: sizes(Sizes) : sizes(Sizes)
{ {
@@ -827,6 +830,14 @@ void AINodeStorage::calculateTownPortalTeleportations(std::vector<CGPathNode *>
actorsOfInitial.insert(aiNode->actor->baseActor); actorsOfInitial.insert(aiNode->actor->baseActor);
} }
std::map<const CGHeroInstance *, int> maskMap;
for(std::shared_ptr<ChainActor> basicActor : actors)
{
if(basicActor->hero)
maskMap[basicActor->hero] = basicActor->chainMask;
}
for(const ChainActor * actor : actorsOfInitial) for(const ChainActor * actor : actorsOfInitial)
{ {
if(!actor->hero) if(!actor->hero)
@@ -851,8 +862,15 @@ void AINodeStorage::calculateTownPortalTeleportations(std::vector<CGPathNode *>
for(const CGTownInstance * targetTown : towns) for(const CGTownInstance * targetTown : towns)
{ {
// TODO: allow to hide visiting hero in garrison // TODO: allow to hide visiting hero in garrison
if(targetTown->visitingHero && targetTown->visitingHero != actor->hero) if(targetTown->visitingHero)
continue; {
auto basicMask = maskMap[targetTown->visitingHero.get()];
bool heroIsInChain = (actor->chainMask & basicMask) != 0;
bool sameActorInTown = actor->chainMask == basicMask;
if(sameActorInTown || !heroIsInChain)
continue;
}
auto nodeOptional = townPortalFinder.createTownPortalNode(targetTown); auto nodeOptional = townPortalFinder.createTownPortalNode(targetTown);

View File

@@ -106,8 +106,6 @@ class AINodeStorage : public INodeStorage
private: private:
int3 sizes; int3 sizes;
/// 1-3 - position on map, 4 - layer (air, water, land), 5 - chain (normal, battle, spellcast and combinations)
boost::multi_array<AIPathNode, 5> nodes;
const CPlayerSpecificInfoCallback * cb; const CPlayerSpecificInfoCallback * cb;
const VCAI * ai; const VCAI * ai;
std::unique_ptr<FuzzyHelper> dangerEvaluator; std::unique_ptr<FuzzyHelper> dangerEvaluator;

View File

@@ -37,7 +37,7 @@ namespace AIPathfinding
AIPathNode * dstMode, AIPathNode * dstMode,
const AIPathNode * srcNode) const override; const AIPathNode * srcNode) const override;
virtual bool canAct(const AIPathNode * source) const; virtual bool canAct(const AIPathNode * source) const override;
virtual const ChainActor * getActor(const ChainActor * sourceActor) const override; virtual const ChainActor * getActor(const ChainActor * sourceActor) const override;

View File

@@ -26,20 +26,12 @@ namespace AIPathfinding
if(source.node->action == CGPathNode::ENodeAction::BLOCKING_VISIT if(source.node->action == CGPathNode::ENodeAction::BLOCKING_VISIT
|| source.node->action == CGPathNode::ENodeAction::VISIT) || source.node->action == CGPathNode::ENodeAction::VISIT)
{ {
if(source.nodeObject) if(source.nodeObject
&& isObjectPassable(source.nodeObject, pathfinderHelper->hero->tempOwner, source.objectRelations))
{ {
if((source.nodeObject->ID == Obj::GARRISON || source.nodeObject->ID == Obj::GARRISON2) return;
&& source.heroRelations != PlayerRelations::ENEMIES)
return;
if(source.nodeObject->ID == Obj::BORDER_GATE)
{
auto quest = dynamic_cast<const CGBorderGate *>(source.nodeObject);
if(quest->wasMyColorVisited(pathfinderHelper->hero->tempOwner))
return;
}
} }
// we can not directly bypass objects, we need to interact with them first // we can not directly bypass objects, we need to interact with them first
destination.node->theNodeBefore = source.node; destination.node->theNodeBefore = source.node;

View File

@@ -30,7 +30,7 @@ extern FuzzyHelper * fh;
class CGVisitableOPW; class CGVisitableOPW;
const float SAFE_ATTACK_CONSTANT = 1.5; const float SAFE_ATTACK_CONSTANT = 1.2;
//one thread may be turn of AI and another will be handling a side effect for AI2 //one thread may be turn of AI and another will be handling a side effect for AI2
boost::thread_specific_ptr<CCallback> cb; boost::thread_specific_ptr<CCallback> cb;
@@ -758,13 +758,12 @@ void VCAI::makeTurn()
boost::shared_lock<boost::shared_mutex> gsLock(CGameState::mutex); boost::shared_lock<boost::shared_mutex> gsLock(CGameState::mutex);
setThreadName("VCAI::makeTurn"); setThreadName("VCAI::makeTurn");
switch(cb->getDate(Date::DAY_OF_WEEK)) if(cb->getDate(Date::DAY_OF_WEEK) == 1)
{
case 1:
{ {
townVisitsThisWeek.clear(); townVisitsThisWeek.clear();
std::vector<const CGObjectInstance *> objs; std::vector<const CGObjectInstance *> objs;
retrieveVisitableObjs(objs, true); retrieveVisitableObjs(objs, true);
for(const CGObjectInstance * obj : objs) for(const CGObjectInstance * obj : objs)
{ {
if(isWeeklyRevisitable(obj)) if(isWeeklyRevisitable(obj))
@@ -773,15 +772,15 @@ void VCAI::makeTurn()
vstd::erase_if_present(alreadyVisited, obj); vstd::erase_if_present(alreadyVisited, obj);
} }
} }
break;
}
} }
markHeroAbleToExplore(primaryHero()); markHeroAbleToExplore(primaryHero());
visitedHeroes.clear(); visitedHeroes.clear();
if(cb->getDate(Date::DAY) == 1) if(cb->getDate(Date::DAY) == 1)
{ {
retrieveVisitableObjs(); retrieveVisitableObjs();
cb->sendMessage("vcmieagles");
} }
try try