From 592e43e11b6d23193e7ee1e663a18875060db27b Mon Sep 17 00:00:00 2001 From: Stubbjax Date: Sun, 23 Aug 2026 22:41:07 +1000 Subject: [PATCH] bugfix: Contact weapons are no longer blocked by obstacles --- Generals/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp | 8 ++++++++ .../Source/GameLogic/Object/Update/AIUpdate.cpp | 4 ++++ .../Code/GameEngine/Source/GameLogic/AI/AIStates.cpp | 8 ++++++++ .../Source/GameLogic/Object/Update/AIUpdate.cpp | 4 ++++ 4 files changed, 24 insertions(+) diff --git a/Generals/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp b/Generals/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp index 385ae65a089..10bcf07ea7a 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp @@ -1214,7 +1214,11 @@ Bool outOfWeaponRangePosition( State *thisState, void* userData ) } Bool viewBlocked = false; +#if RETAIL_COMPATIBLE_CRC if (onGround) +#else + if (onGround && !weapon->isContactWeapon()) +#endif { viewBlocked = TheAI->pathfinder()->isAttackViewBlockedByObstacle(obj, *obj->getPosition(), nullptr, *pos); } @@ -2654,7 +2658,11 @@ StateReturnType AIAttackApproachTargetState::updateInternal() if (m_stopIfInRange && weapon && weapon->isWithinAttackRange(source, &m_goalPosition)) { Bool viewBlocked = false; +#if RETAIL_COMPATIBLE_CRC if ( ai->isDoingGroundMovement() ) +#else + if ( ai->isDoingGroundMovement() && !weapon->isContactWeapon() ) +#endif { viewBlocked = TheAI->pathfinder()->isAttackViewBlockedByObstacle(source, *source->getPosition(), nullptr, m_goalPosition); } diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp index c49ae77d861..ceaa3fd6ddc 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp @@ -3399,7 +3399,11 @@ void AIUpdateInterface::privateAttackPosition( const Coord3D *pos, Int maxShotsT // this fixes an obscure bug with mine-clearing: if you tell someone to clear mines and put the centerpoint // inside a building, the dozer/worker will just go thru the building to that spot. ick. so if you find that // this clause (below) is problematic, you'll probably have to find another way to fix this mine-clearing bug. (srj) +#if RETAIL_COMPATIBLE_CRC if (weapon && weapon->isContactWeapon() && !isPathAvailable(&localPos)) +#else + if (weapon && weapon->isContactWeapon() && !weapon->isWithinAttackRange(getObject(), &localPos) && !isPathAvailable(&localPos)) +#endif { FindPositionOptions fpOptions; fpOptions.minRadius = 0.0f; diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp index 93474df91f7..12a5fd547a2 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp @@ -1219,7 +1219,11 @@ Bool outOfWeaponRangePosition( State *thisState, void* userData ) } Bool viewBlocked = false; +#if RETAIL_COMPATIBLE_CRC if (onGround) +#else + if (onGround && !weapon->isContactWeapon()) +#endif { viewBlocked = TheAI->pathfinder()->isAttackViewBlockedByObstacle(obj, *obj->getPosition(), nullptr, *pos); } @@ -2740,7 +2744,11 @@ StateReturnType AIAttackApproachTargetState::updateInternal() if (m_stopIfInRange && weapon && weapon->isWithinAttackRange(source, &m_goalPosition)) { Bool viewBlocked = false; +#if RETAIL_COMPATIBLE_CRC if ( ai->isDoingGroundMovement() ) +#else + if ( ai->isDoingGroundMovement() && !weapon->isContactWeapon() ) +#endif { viewBlocked = TheAI->pathfinder()->isAttackViewBlockedByObstacle(source, *source->getPosition(), nullptr, m_goalPosition); } diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp index 977aec18670..6f9384af00a 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp @@ -3554,7 +3554,11 @@ void AIUpdateInterface::privateAttackPosition( const Coord3D *pos, Int maxShotsT // this fixes an obscure bug with mine-clearing: if you tell someone to clear mines and put the centerpoint // inside a building, the dozer/worker will just go thru the building to that spot. ick. so if you find that // this clause (below) is problematic, you'll probably have to find another way to fix this mine-clearing bug. (srj) +#if RETAIL_COMPATIBLE_CRC if (weapon && weapon->isContactWeapon() && !isPathAvailable(&localPos)) +#else + if (weapon && weapon->isContactWeapon() && !weapon->isWithinAttackRange(getObject(), &localPos) && !isPathAvailable(&localPos)) +#endif { FindPositionOptions fpOptions; fpOptions.minRadius = 0.0f;