Browse Source

Merge pull request #3600 from dydzio0614/sod-fly

Fix SoD fly mechanics
Ivan Savenko 1 year ago
parent
commit
ad602573ff

+ 3 - 1
config/gameConfig.json

@@ -384,7 +384,9 @@
 			// if enabled, pathfinder will take use of one-way monoliths with multiple exits.
 			"useMonolithOneWayRandom" : false,
 			// if enabled and hero has whirlpool protection effect, pathfinder will take use of whirpools
-			"useWhirlpool" : true
+			"useWhirlpool" : true,
+			// if enabled flying will work like in original game, otherwise nerf similar to HotA flying is applied
+			"originalFlyRules" : false
 		},
 		
 		"bonuses" : 

+ 1 - 0
lib/GameSettings.cpp

@@ -102,6 +102,7 @@ void GameSettings::load(const JsonNode & input)
 		{EGameSettings::PATHFINDER_USE_MONOLITH_ONE_WAY_UNIQUE, "pathfinder", "useMonolithOneWayUnique"   },
 		{EGameSettings::PATHFINDER_USE_MONOLITH_ONE_WAY_RANDOM, "pathfinder", "useMonolithOneWayRandom"   },
 		{EGameSettings::PATHFINDER_USE_WHIRLPOOL,               "pathfinder", "useWhirlpool"              },
+		{EGameSettings::PATHFINDER_ORIGINAL_FLY_RULES,          "pathfinder", "originalFlyRules"          },
 		{EGameSettings::TOWNS_BUILDINGS_PER_TURN_CAP,           "towns",     "buildingsPerTurnCap"        },
 		{EGameSettings::TOWNS_STARTING_DWELLING_CHANCES,        "towns",     "startingDwellingChances"    },
 	};

+ 1 - 0
lib/GameSettings.h

@@ -66,6 +66,7 @@ enum class EGameSettings
 	PATHFINDER_USE_MONOLITH_ONE_WAY_UNIQUE,
 	PATHFINDER_USE_MONOLITH_ONE_WAY_RANDOM,
 	PATHFINDER_USE_WHIRLPOOL,
+	PATHFINDER_ORIGINAL_FLY_RULES,
 	TOWNS_BUILDINGS_PER_TURN_CAP,
 	TOWNS_STARTING_DWELLING_CHANCES,
 	COMBAT_ONE_HEX_TRIGGERS_OBSTACLES,

+ 1 - 1
lib/pathfinder/CPathfinder.cpp

@@ -483,7 +483,7 @@ bool CPathfinderHelper::passOneTurnLimitCheck(const PathNodeInfo & source) const
 		return false;
 	if(source.node->layer == EPathfindingLayer::AIR)
 	{
-		return options.originalMovementRules && source.node->accessible == EPathAccessibility::ACCESSIBLE;
+		return options.originalFlyRules && source.node->accessible == EPathAccessibility::ACCESSIBLE;
 	}
 
 	return true;

+ 1 - 1
lib/pathfinder/PathfinderOptions.cpp

@@ -27,10 +27,10 @@ PathfinderOptions::PathfinderOptions()
 	, useTeleportOneWay(VLC->settings()->getBoolean(EGameSettings::PATHFINDER_USE_MONOLITH_ONE_WAY_UNIQUE))
 	, useTeleportOneWayRandom(VLC->settings()->getBoolean(EGameSettings::PATHFINDER_USE_MONOLITH_ONE_WAY_RANDOM))
 	, useTeleportWhirlpool(VLC->settings()->getBoolean(EGameSettings::PATHFINDER_USE_WHIRLPOOL))
+	, originalFlyRules(VLC->settings()->getBoolean(EGameSettings::PATHFINDER_ORIGINAL_FLY_RULES))
 	, useCastleGate(false)
 	, lightweightFlyingMode(false)
 	, oneTurnSpecialLayersLimit(true)
-	, originalMovementRules(false)
 	, turnLimit(std::numeric_limits<uint8_t>::max())
 	, canUseCast(false)
 {

+ 3 - 1
lib/pathfinder/PathfinderOptions.h

@@ -67,7 +67,9 @@ struct DLL_LINKAGE PathfinderOptions
 	/// - Option should also allow same tile land <-> air layer transitions.
 	///   Current implementation only allow go into (from) air layer only to neighbour tiles.
 	///   I find it's reasonable limitation, but it's will make some movements more expensive than in H3.
-	bool originalMovementRules;
+	///   Further work can also be done to mimic SoD quirks if needed
+	///   (such as picking unoptimal paths on purpose when targeting guards or being interrupted on guarded resource tile when picking it during diagonal u-turn)
+	bool originalFlyRules;
 
 	/// Max number of turns to compute. Default = infinite
 	uint8_t turnLimit;

+ 15 - 7
lib/pathfinder/PathfindingRules.cpp

@@ -301,7 +301,7 @@ PathfinderBlockingRule::BlockingReason MovementToDestinationRule::getBlockingRea
 
 		if(source.guarded)
 		{
-			if(!(pathfinderConfig->options.originalMovementRules && source.node->layer == EPathfindingLayer::AIR) 
+			if(!(pathfinderConfig->options.originalFlyRules && source.node->layer == EPathfindingLayer::AIR)
 				&& !pathfinderConfig->options.ignoreGuards
 				&&	(!destination.isGuardianTile || pathfinderHelper->getGuardiansCount(source.coord) > 1)) // Can step into tile of guard
 			{
@@ -386,14 +386,22 @@ void LayerTransitionRule::process(
 		break;
 
 	case EPathfindingLayer::AIR:
-		if(pathfinderConfig->options.originalMovementRules)
+		if(pathfinderConfig->options.originalFlyRules)
 		{
-			if((source.node->accessible != EPathAccessibility::ACCESSIBLE &&
-				source.node->accessible != EPathAccessibility::VISITABLE) &&
-				(destination.node->accessible != EPathAccessibility::VISITABLE &&
-				 destination.node->accessible != EPathAccessibility::ACCESSIBLE))
+			if(source.node->accessible != EPathAccessibility::ACCESSIBLE &&
+				source.node->accessible != EPathAccessibility::VISITABLE &&
+				destination.node->accessible != EPathAccessibility::VISITABLE &&
+				 destination.node->accessible != EPathAccessibility::ACCESSIBLE)
 			{
-				destination.blocked = true;
+				if(destination.node->accessible == EPathAccessibility::BLOCKVIS)
+				{
+					if(source.nodeObject || (source.tile->blocked && destination.tile->blocked))
+					{
+						destination.blocked = true;
+					}
+				}
+				else
+					destination.blocked = true;
 			}
 		}
 		else if(destination.node->accessible != EPathAccessibility::ACCESSIBLE)

+ 1 - 1
server/CGameHandler.cpp

@@ -1195,7 +1195,7 @@ bool CGameHandler::moveHero(ObjectInstanceID hid, int3 dst, ui8 teleporting, boo
 		if (leavingTile == LEAVING_TILE)
 			leaveTile();
 
-		if (isInTheMap(guardPos))
+		if (lookForGuards == CHECK_FOR_GUARDS && isInTheMap(guardPos))
 			tmh.attackedFrom = std::make_optional(guardPos);
 
 		tmh.result = result;