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:
		
				
					committed by
					
						 Andrii Danylchenko
						Andrii Danylchenko
					
				
			
			
				
	
			
			
			
						parent
						
							1a69a43f09
						
					
				
				
					commit
					e95ccda5de
				
			| @@ -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) | ||||||
|   | |||||||
| @@ -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); | ||||||
|   | |||||||
| @@ -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; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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; | ||||||
|   | |||||||
| @@ -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; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user