Skip to content
Open
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
10 changes: 10 additions & 0 deletions Core/GameEngine/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -491,6 +491,7 @@ set(GAMEENGINE_SRC
Include/GameLogic/Pathfinder/PathfindCell.h
Include/GameLogic/Pathfinder/PathfindCellInfo.h
Include/GameLogic/Pathfinder/PathfindCellList.h
Include/GameLogic/Pathfinder/PathfindConstants.h
Include/GameLogic/Pathfinder/PathfindLayer.h
Include/GameLogic/Pathfinder/PathfindZoneManager.h
Include/GameLogic/Pathfinder/PathNode.h
Expand Down Expand Up @@ -862,6 +863,15 @@ set(GAMEENGINE_SRC
# Source/GameLogic/AI/AISkirmishPlayer.cpp
# Source/GameLogic/AI/AIStates.cpp
# Source/GameLogic/AI/AITNGuard.cpp
Source/GameLogic/AI/Pathfinder/Path.cpp
Source/GameLogic/AI/Pathfinder/PathfindCell.cpp
Source/GameLogic/AI/Pathfinder/PathfindCellInfo.cpp
Source/GameLogic/AI/Pathfinder/PathfindCellList.cpp
Source/GameLogic/AI/Pathfinder/PathfindConstants.cpp
Source/GameLogic/AI/Pathfinder/PathfindLayer.cpp
Source/GameLogic/AI/Pathfinder/PathfindZoneManager.cpp
Source/GameLogic/AI/Pathfinder/PathNode.cpp
Source/GameLogic/AI/Pathfinder/ZoneBlock.cpp
# Source/GameLogic/AI/Squad.cpp
# Source/GameLogic/AI/TurretAI.cpp
Source/GameLogic/Map/PolygonTrigger.cpp
Expand Down
10 changes: 1 addition & 9 deletions Core/GameEngine/Include/GameLogic/AIPathfind.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#include "Pathfinder/PathfindCell.h"
#include "Pathfinder/PathfindCellInfo.h"
#include "Pathfinder/PathfindCellList.h"
#include "Pathfinder/PathfindConstants.h"
#include "Pathfinder/PathfindLayer.h"
#include "Pathfinder/PathfindZoneManager.h"
#include "Pathfinder/PathNode.h"
Expand Down Expand Up @@ -67,16 +68,7 @@ class PathfindCell;
// See GameType.h for
// enum {LAYER_INVALID = 0, LAYER_GROUND = 1, LAYER_TOP=2 };

// Fits in 4 bits for now
enum {MAX_WALL_PIECES = 128};

// how close a unit has to be in z to interact with the layer.
#define LAYER_Z_CLOSE_ENOUGH_F 10.0f

#define PATHFIND_CELL_SIZE 10
#define PATHFIND_CELL_SIZE_F 10.0f

enum { PATHFIND_QUEUE_LEN=512};

struct TCheckMovementInfo;

Expand Down
19 changes: 13 additions & 6 deletions Core/GameEngine/Include/GameLogic/Pathfinder/PathfindCell.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,8 @@ class PathfindCell
void clearObstruction() { m_type = CELL_CLEAR; m_obstacleID = INVALID_ID; m_obstacleIsFence = false; m_obstacleIsTransparent = false; }
#endif

inline Bool isObstacleTransparent() const;
inline Bool isObstacleFence() const;
Bool isObstacleTransparent() const;
Bool isObstacleFence() const;

/// Return estimated cost from given cell to reach goal cell
UnsignedInt costToGoal( PathfindCell *goal );
Expand Down Expand Up @@ -124,15 +124,15 @@ class PathfindCell
inline UnsignedShort getXIndex() const {return m_info->m_pos.x;}
inline UnsignedShort getYIndex() const {return m_info->m_pos.y;}

inline Bool isBlockedByAlly() const;

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Compiler didn't want to play nice with some of the functions being inlined, so it was removed.

inline void setBlockedByAlly(Bool blocked);
Bool isBlockedByAlly() const;
void setBlockedByAlly(Bool blocked);

inline Bool getOpen() const {return m_info->m_open;}
inline Bool getClosed() const {return m_info->m_closed;}
inline UnsignedInt getCostSoFar() const {return m_info->m_costSoFar;}
inline UnsignedInt getTotalCost() const {return m_info->m_totalCost;}

inline UnsignedInt getTotalCostDifference(PathfindCell& other) const;
UnsignedInt getTotalCostDifference(PathfindCell& other) const;

inline void setCostSoFar(UnsignedInt cost) { if( m_info ) m_info->m_costSoFar = cost;}
inline void setTotalCost(UnsignedInt cost) { if( m_info ) m_info->m_totalCost = cost;}
Expand All @@ -158,14 +158,21 @@ class PathfindCell
inline ObjectID getGoalAircraft() const {ObjectID id = m_info?m_info->m_goalAircraftID:INVALID_ID; return id;}
inline ObjectID getPosUnit() const {ObjectID id = m_info?m_info->m_posUnitID:INVALID_ID; return id;}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could remove the inline keyword from all of these. They are already implicitly inline.


inline ObjectID getObstacleID() const;
ObjectID getObstacleID() const;

void setLayer( PathfindLayerEnum layer ) { m_layer = layer; } ///< set the cell layer
PathfindLayerEnum getLayer() const { return (PathfindLayerEnum)m_layer; } ///< get the cell layer

void setConnectLayer( PathfindLayerEnum layer ) { m_connectsToLayer = layer; } ///< set the cell layer connect id
PathfindLayerEnum getConnectLayer() const { return (PathfindLayerEnum)m_connectsToLayer; } ///< get the cell layer connect id

static Bool typesMatch(const PathfindCell& targetCell, const PathfindCell& sourceCell);

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These were global functions that better fit as a static function in the PathfindCell class

static Bool waterGround(const PathfindCell& targetCell, const PathfindCell& sourceCell);
static Bool groundRubble(const PathfindCell& targetCell, const PathfindCell& sourceCell);
static Bool terrain(const PathfindCell& targetCell, const PathfindCell& sourceCell);
static Bool crusherGround(const PathfindCell& targetCell, const PathfindCell& sourceCell);
static Bool groundCliff(const PathfindCell& targetCell, const PathfindCell& sourceCell);

private:
PathfindCellInfo *m_info;
ObjectID m_obstacleID; ///< the object ID who overlaps this cell
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,12 @@ class PathfindCellInfo
static void releaseACellInfo(PathfindCellInfo *theInfo);

protected:
#if RETAIL_COMPATIBLE_PATHFINDING
#define CELL_INFOS_TO_ALLOCATE 30000
#else
static constexpr const UnsignedInt CELL_INFOS_TO_ALLOCATE = 30000;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this need to be in the header?

#endif

static PathfindCellInfo *s_infoArray;
static PathfindCellInfo *s_firstFree; ///<

Expand Down
46 changes: 46 additions & 0 deletions Core/GameEngine/Include/GameLogic/Pathfinder/PathfindConstants.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
** Command & Conquer Generals Zero Hour(tm)
** Copyright 2025 TheSuperHackers

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 New comments use last year

The newly written copyright comments in PathfindConstants.h and PathfindConstants.cpp use 2025. The repository rule disallows dates before 2026 in new comments. Update both to the current year to satisfy this requirement before merging.

Rule Used: What: Flag newly created code comments that reference dates prior to the current year (2026). Why: Ensuring comments are up-to-date helps maintain relevance and accuracy in the codebase. Good: // This function was created in 2026. Bad: ```... (source)

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#define MAX_WALL_PIECES 128

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Header has no include protection

The new PathfindConstants.h has no include protection. The repository requires #pragma once in headers. Add it before the declarations to satisfy this requirement before merging.

Suggested change
#define MAX_WALL_PIECES 128
#pragma once
#define MAX_WALL_PIECES 128

Rule Used: Use #pragma once for header include protection instead of traditional include guards (#ifndef/#define/#endif). The pragma directive alone is sufficient and avoids redundancy, macro name conflicts, and unnecessary boilerplate code. (source)

Learned From
TheSuperHackers/GeneralsGameCode#2067

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

#define PATHFIND_QUEUE_LEN 512

// how close a unit has to be in z to interact with the layer.
extern const Real LAYER_Z_CLOSE_ENOUGH_F;

extern const UnsignedInt PATHFIND_CELL_SIZE;
extern const Real PATHFIND_CELL_SIZE_F;

extern const UnsignedInt ZONE_UPDATE_FREQUENCY;
extern const UnsignedInt MAX_CELL_COUNT;
extern const UnsignedInt MAX_ADJUSTMENT_CELL_COUNT;
extern const UnsignedInt MAX_SAFE_PATH_CELL_COUNT;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we do constexpr const UnsignedInt MAX_SAFE_PATH_CELL_COUNT = ??; ?

I think it would compile on VC6 and modern build.


// Number of cells we will search pathfinding per frame.
extern const UnsignedInt PATHFIND_CELLS_PER_FRAME;

extern const Int COST_ORTHOGONAL;
extern const Int COST_DIAGONAL;
extern const Real COST_TO_DISTANCE_FACTOR;
extern const Real COST_TO_DISTANCE_FACTOR_SQR;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume all of these constants in this file are used by at least 2 isolated cpp's?

Or would some of these be better fits closer to closely related classes in headers?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They are used in multiple classes. When we revisit each class, we will have a look if they have a better place.


#if RETAIL_COMPATIBLE_PATHFINDING
// TheSuperHackers @info This variable is here so the code will run down the retail compatible path till a failure mode is hit
// The pathfinding will then switch over to the corrected pathfinding code for SH clients
extern Bool s_useFixedPathfinding;
extern Bool s_forceCleanCells;
#endif
6 changes: 6 additions & 0 deletions Core/GameEngine/Include/GameLogic/Pathfinder/ZoneBlock.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,12 @@ class ZoneBlock
Bool getInteractsWithBridge() const {return m_interactsWithBridge;}
void setInteractsWithBridge(Bool interacts) {m_interactsWithBridge = interacts;}

static void __fastcall resolveBlockZones(Int srcZone, Int targetZone, zoneStorageType* zoneEquivalency, Int sizeOfZE);
static void __fastcall resolveZones(Int srcZone, Int targetZone, zoneStorageType* zoneEquivalency, Int sizeOfZE);
static void flattenZones(zoneStorageType* zoneArray, zoneStorageType* zoneHierarchical, Int sizeOfZones);
static void applyZone(PathfindCell& targetCell, const PathfindCell& sourceCell, zoneStorageType* zoneEquivalency, Int sizeOfZE);
static void applyBlockZone(PathfindCell& targetCell, const PathfindCell& sourceCell, zoneStorageType* zoneEquivalency, Int firstZone, Int sizeOfZE);

protected:
void allocateZones();
void freeZones();
Expand Down
Loading
Loading