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;
}
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
{
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
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 isWeeklyRevisitable(const CGObjectInstance * obj);

View File

@@ -113,6 +113,7 @@ const CGObjectInstance * ObjectClusterizer::getBlocker(const AIPath & path) cons
|| blocker->ID == Obj::QUEST_GUARD
|| blocker->ID == Obj::BORDER_GATE)
{
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);
if(node->coord == blockerPos)
if(node->coord == blockerPos || cb->getGuardingCreaturePosition(node->coord) == blockerPos)
break;
}

View File

@@ -19,6 +19,9 @@
#include "../../../lib/PathfinderUtil.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)
: sizes(Sizes)
{
@@ -827,6 +830,14 @@ void AINodeStorage::calculateTownPortalTeleportations(std::vector<CGPathNode *>
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)
{
if(!actor->hero)
@@ -851,8 +862,15 @@ void AINodeStorage::calculateTownPortalTeleportations(std::vector<CGPathNode *>
for(const CGTownInstance * targetTown : towns)
{
// TODO: allow to hide visiting hero in garrison
if(targetTown->visitingHero && targetTown->visitingHero != actor->hero)
if(targetTown->visitingHero)
{
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);

View File

@@ -106,8 +106,6 @@ class AINodeStorage : public INodeStorage
private:
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 VCAI * ai;
std::unique_ptr<FuzzyHelper> dangerEvaluator;

View File

@@ -37,7 +37,7 @@ namespace AIPathfinding
AIPathNode * dstMode,
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;

View File

@@ -26,20 +26,12 @@ namespace AIPathfinding
if(source.node->action == CGPathNode::ENodeAction::BLOCKING_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)
&& 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
destination.node->theNodeBefore = source.node;

View File

@@ -30,7 +30,7 @@ extern FuzzyHelper * fh;
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
boost::thread_specific_ptr<CCallback> cb;
@@ -758,13 +758,12 @@ void VCAI::makeTurn()
boost::shared_lock<boost::shared_mutex> gsLock(CGameState::mutex);
setThreadName("VCAI::makeTurn");
switch(cb->getDate(Date::DAY_OF_WEEK))
{
case 1:
if(cb->getDate(Date::DAY_OF_WEEK) == 1)
{
townVisitsThisWeek.clear();
std::vector<const CGObjectInstance *> objs;
retrieveVisitableObjs(objs, true);
for(const CGObjectInstance * obj : objs)
{
if(isWeeklyRevisitable(obj))
@@ -773,15 +772,15 @@ void VCAI::makeTurn()
vstd::erase_if_present(alreadyVisited, obj);
}
}
break;
}
}
markHeroAbleToExplore(primaryHero());
visitedHeroes.clear();
if(cb->getDate(Date::DAY) == 1)
{
retrieveVisitableObjs();
cb->sendMessage("vcmieagles");
}
try