Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion Core/GameEngine/Include/GameLogic/AIPathfind.h
Original file line number Diff line number Diff line change
Expand Up @@ -388,9 +388,11 @@ class Pathfinder : PathfindServicesInterface, public Snapshot
Int m_queuePRTail;
Int m_cumulativeCellsAllocated;

#if RTS_ZEROHOUR && RETAIL_COMPATIBLE_CRC
#if RTS_ZEROHOUR && RETAIL_COMPATIBLE_PATHFINDING
public:
Bool m_classifyFenceZeroInit;
UnsignedByte m_tightenPathSpecialInit;
Coord3D m_tightenPathSpecialInitCoords;
#endif
};

Expand Down
5 changes: 5 additions & 0 deletions Core/GameEngine/Include/GameLogic/TerrainLogic.h
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,11 @@ class Bridge : public MemoryPoolObject
void setBridgeObjectID( ObjectID id ) { m_bridgeInfo.bridgeObjectID = id; }
void setTowerObjectID( ObjectID id, BridgeTowerType which ) { m_bridgeInfo.towerObjectID[ which ] = id; }

#if RTS_ZEROHOUR && RETAIL_COMPATIBLE_PATHFINDING
private:
Bool isPointOnBridge_SpecialInit(const Coord3D& pos, Bool specialInit, Coord3D& out) const;
#endif

};

//-------------------------------------------------------------------------------------------------
Expand Down
34 changes: 30 additions & 4 deletions Core/GameEngine/Source/GameLogic/AI/AIPathfind.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -225,8 +225,10 @@ void Pathfinder::reset()
s_forceCleanCells = false;
#endif

#if RTS_ZEROHOUR && RETAIL_COMPATIBLE_CRC
#if RTS_ZEROHOUR && RETAIL_COMPATIBLE_PATHFINDING
m_classifyFenceZeroInit = false;
m_tightenPathSpecialInit = 0;
m_tightenPathSpecialInitCoords.zero();
#endif
}

Expand Down Expand Up @@ -364,7 +366,7 @@ void Pathfinder::classifyFence( Object *obj, Bool insert )
cellBounds.lo.x = REAL_TO_INT_FLOOR((pos->x + 0.5f)/PATHFIND_CELL_SIZE_F);
cellBounds.lo.y = REAL_TO_INT_FLOOR((pos->y + 0.5f)/PATHFIND_CELL_SIZE_F);
// TheSuperHackers @fix Mauller 16/06/2025 Fixes uninitialized variables.
#if RETAIL_COMPATIBLE_CRC
#if RETAIL_COMPATIBLE_PATHFINDING
//CRCDEBUG_LOG(("Pathfinder::classifyFence - (%d,%d)", cellBounds.hi.x, cellBounds.hi.y));

// For retail the values on the stack are often either 0 or larger than the map size.
Expand Down Expand Up @@ -1496,12 +1498,20 @@ Bool Pathfinder::checkForAdjust(Object *obj, const LocomotorSet& locomotorSet, B
if (obj->isKindOf(KINDOF_AIRCRAFT)) {
adjustedPathExists = true;
} else {
#if RTS_ZEROHOUR && RETAIL_COMPATIBLE_PATHFINDING
m_tightenPathSpecialInit = groupDest != nullptr;
#endif

Bool pathExists = clientSafeQuickDoesPathExist( locomotorSet, obj->getPosition(), dest);
if (!pathExists && clientSafeQuickDoesPathExist( locomotorSet, dest, &adjustDest)) {
adjustedPathExists = true;
} else {
adjustedPathExists = clientSafeQuickDoesPathExist( locomotorSet, obj->getPosition(), &adjustDest);
}

#if RTS_ZEROHOUR && RETAIL_COMPATIBLE_PATHFINDING
m_tightenPathSpecialInit = 0;
#endif
}
if ( adjustedPathExists ) {
if (groupDest) {
Expand Down Expand Up @@ -1647,6 +1657,10 @@ Bool Pathfinder::adjustDestination(Object *obj, const LocomotorSet& locomotorSet
layer = TheTerrainLogic->getLayerForDestination(groupDest);
}

#if RTS_ZEROHOUR && RETAIL_COMPATIBLE_PATHFINDING
m_tightenPathSpecialInitCoords.zero();
#endif

Int i = cell.x;
Int j = cell.y;
// Check the center cell
Expand Down Expand Up @@ -4569,14 +4583,26 @@ void Pathfinder::tightenPath(Object *obj, const LocomotorSet& locomotorSet, Coor
TightenPathStruct info;

getRadiusAndCenter(obj, info.radius, info.center);
info.layer = TheTerrainLogic->getLayerForDestination(from);
info.obj = obj;
info.locomotorSet = &locomotorSet;
info.foundNewDest = false;
info.orgDestPos = *to;
#if RETAIL_COMPATIBLE_CRC
#if RETAIL_COMPATIBLE_PATHFINDING

#if RTS_ZEROHOUR
m_tightenPathSpecialInit = 2;
info.layer = TheTerrainLogic->getLayerForDestination(from);
m_tightenPathSpecialInit = 0;

info.newDestPos = m_tightenPathSpecialInitCoords;
#else
info.layer = TheTerrainLogic->getLayerForDestination(from);
info.newDestPos.zero();
#endif

#else
info.layer = TheTerrainLogic->getLayerForDestination(from);
#endif
iterateCellsAlongLine(*from, *to, info.layer, tightenPathCallback, &info);
if (info.foundNewDest) {
*from = info.newDestPos;
Expand Down
70 changes: 70 additions & 0 deletions Core/GameEngine/Source/GameLogic/Map/TerrainLogic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,14 @@ Bool Bridge::isPointOnBridge(const Coord3D *pLoc)
if (pLoc->y < m_bounds.lo.y) return(false);
if (pLoc->y > m_bounds.hi.y) return(false);

#if RTS_ZEROHOUR && RETAIL_COMPATIBLE_PATHFINDING
Pathfinder& pathfinder = *TheAI->pathfinder();
if (pathfinder.m_tightenPathSpecialInit)
{
return isPointOnBridge_SpecialInit(*pLoc, pathfinder.m_tightenPathSpecialInit == 2, pathfinder.m_tightenPathSpecialInitCoords);
}
#endif

Vector3 testPt(pLoc->x, pLoc->y, pLoc->z);
Vector3 left1(m_bridgeInfo.fromLeft.x, m_bridgeInfo.fromLeft.y, m_bridgeInfo.fromLeft.z);
Vector3 right1(m_bridgeInfo.fromRight.x, m_bridgeInfo.fromRight.y, m_bridgeInfo.fromRight.z);
Expand All @@ -452,6 +460,68 @@ Bool Bridge::isPointOnBridge(const Coord3D *pLoc)
return(false);
}

#if RTS_ZEROHOUR && RETAIL_COMPATIBLE_PATHFINDING
// TheSuperHackers @info Caball009 11/11/2026 Special version of function Bridge::isPointOnBridge for retail compatibility.
// The purpose of this function is to get the values for the originally uninitialized variable in Pathfinder::tightenPathCallback.
Bool Bridge::isPointOnBridge_SpecialInit(const Coord3D& pos, Bool specialInit, Coord3D& out) const
{
const Vector3 testPt(pos.x, pos.y, pos.z);
const Vector3 left1(m_bridgeInfo.fromLeft.x, m_bridgeInfo.fromLeft.y, m_bridgeInfo.fromLeft.z);
const Vector3 right1(m_bridgeInfo.fromRight.x, m_bridgeInfo.fromRight.y, m_bridgeInfo.fromRight.z);
const Vector3 left2(m_bridgeInfo.toLeft.x, m_bridgeInfo.toLeft.y, m_bridgeInfo.toLeft.z);
const Vector3 right2(m_bridgeInfo.toRight.x, m_bridgeInfo.toRight.y, m_bridgeInfo.toRight.z);

unsigned char flags;

if (Point_In_Triangle_2D(left1, right1, left2, testPt, 0, 1, flags))
{
if (specialInit)
{
const Vector3& tri_point0 = left1;
const Vector3& tri_point1 = right1;

const Vector2 p0p1(tri_point1[0] - tri_point0[0], tri_point1[1] - tri_point0[1]);
const Vector2 p0pT(testPt[0] - tri_point0[0], testPt[1] - tri_point0[1]);
const float z = Vector2::Perp_Dot_Product(p0p1, p0pT);

out.set(p0p1.X, p0p1.Y, z);
}
else
{
out.set(0.0f, 1000000000.0f, 0.0f);
}

return true;
}
else
{
const bool inTriangle = Point_In_Triangle_2D(right1, left2, right2, testPt, 0, 1, flags);

if (specialInit)
{
const Vector3& tri_point0 = right1;
const Vector3& tri_point1 = left2;

const Vector2 p0p1(tri_point1[0] - tri_point0[0], tri_point1[1] - tri_point0[1]);
const Vector2 p0pT(testPt[0] - tri_point0[0], testPt[1] - tri_point0[1]);
const float z = Vector2::Perp_Dot_Product(p0p1, p0pT);

out.set(p0p1.X, p0p1.Y, z);
}
else if (inTriangle)
{
out.set(0.0f, 1000000000.0f, 0.0f);
}
else
{
out.set(0.0f, 0.0f, 0.0f);
}

return inTriangle;
}
}
#endif // RTS_ZEROHOUR && RETAIL_COMPATIBLE_PATHFINDING

/*-------------------------------------------------------------------------------------------------
/** Clip a floating point line to the region provided. The source line runs from p1 to p2, and is clipped
* using the clipRegion.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2537,7 +2537,7 @@ void GameLogic::processDestroyList()
{
//USE_PERF_TIMER(processDestroyList)

#if RTS_ZEROHOUR && RETAIL_COMPATIBLE_CRC
#if RTS_ZEROHOUR && RETAIL_COMPATIBLE_PATHFINDING
// TheSuperHackers @info Set m_classifyFenceZeroInit to true for the first object. It's set to false when this function exits.
// Pathfinder::classifyFence may be called indirectly from Object::~Object.
TheAI->pathfinder()->m_classifyFenceZeroInit = !m_objectsToDestroy.empty();
Expand Down Expand Up @@ -2602,7 +2602,7 @@ void GameLogic::processDestroyList()

Object::friend_deleteInstance(currentObject);//actual delete

#if RTS_ZEROHOUR && RETAIL_COMPATIBLE_CRC
#if RTS_ZEROHOUR && RETAIL_COMPATIBLE_PATHFINDING
TheAI->pathfinder()->m_classifyFenceZeroInit = false;
#endif
}
Expand Down
Loading