Skip to content

Commit 41a848c

Browse files
authored
unify(pathfinder): Merge PathfindLayer::doDebugIcons(), Pathfinder::Classify functions, Pathfinder::checkDestination() and Pathfinder::checkForMovement() (TheSuperHackers#2414)
1 parent 6b726d7 commit 41a848c

2 files changed

Lines changed: 292 additions & 10 deletions

File tree

Generals/Code/GameEngine/Source/GameLogic/AI/AIPathfind.cpp

Lines changed: 180 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3322,6 +3322,10 @@ void PathfindLayer::doDebugIcons() {
33223322
if (m_layer == LAYER_WALL) {
33233323
bridgeHeight = TheAI->pathfinder()->getWallHeight();
33243324
}
3325+
static Int flash = 0;
3326+
flash--;
3327+
if (flash<1) flash = 20;
3328+
if (flash < 10) return;
33253329
Bool showCells = TheGlobalData->m_debugAI==AI_DEBUG_CELLS;
33263330
// show the pathfind grid
33273331
for( int j=0; j<m_height; j++ )
@@ -3333,8 +3337,8 @@ void PathfindLayer::doDebugIcons() {
33333337
topLeftCorner.x = (Real)(i+m_xOrigin) * PATHFIND_CELL_SIZE_F;
33343338

33353339
color.red = color.green = color.blue = 0;
3336-
Bool empty = true;
3337-
3340+
Bool empty = false;
3341+
Real size = 0.4f;
33383342
const PathfindCell *cell = &m_layerCells[i][j];
33393343
if (cell)
33403344
{
@@ -3344,13 +3348,16 @@ void PathfindLayer::doDebugIcons() {
33443348
empty = false;
33453349
} else if (cell->getType() == PathfindCell::CELL_IMPASSABLE) {
33463350
color.red = color.green = color.blue = 1;
3351+
size = 0.2f;
33473352
empty = false;
33483353
} else if (cell->getType() == PathfindCell::CELL_BRIDGE_IMPASSABLE) {
33493354
color.blue = color.red = 1;
33503355
empty = false;
33513356
} else if (cell->getType() == PathfindCell::CELL_CLIFF) {
33523357
color.red = 1;
33533358
empty = false;
3359+
} else {
3360+
size = 0.2f;
33543361
}
33553362
}
33563363
if (showCells) {
@@ -3376,7 +3383,7 @@ void PathfindLayer::doDebugIcons() {
33763383
loc.x = topLeftCorner.x + PATHFIND_CELL_SIZE_F/2.0f;
33773384
loc.y = topLeftCorner.y + PATHFIND_CELL_SIZE_F/2.0f;
33783385
loc.z = bridgeHeight;
3379-
addIcon(&loc, PATHFIND_CELL_SIZE_F*0.8f, 99, color);
3386+
addIcon(&loc, PATHFIND_CELL_SIZE_F*size, 99, color);
33803387
}
33813388
}
33823389
}
@@ -3570,7 +3577,11 @@ void PathfindLayer::classifyCells()
35703577
groundCell->setConnectLayer(LAYER_INVALID); // disconnect it.
35713578
}
35723579
}
3580+
#if RTS_GENERALS && RETAIL_COMPATIBLE_PATHFINDING
35733581
cell->setType(PathfindCell::CELL_IMPASSABLE);
3582+
#else
3583+
cell->setType(PathfindCell::CELL_BRIDGE_IMPASSABLE);
3584+
#endif
35743585
}
35753586
}
35763587
}
@@ -3735,7 +3746,11 @@ void PathfindLayer::classifyLayerMapCell( Int i, Int j , PathfindCell *cell, Bri
37353746
cell->setType(PathfindCell::CELL_CLEAR);
37363747
} else {
37373748
if (bridgeCount!=0) {
3749+
#if RTS_GENERALS && RETAIL_COMPATIBLE_PATHFINDING
37383750
cell->setType(PathfindCell::CELL_CLIFF); // it's off the bridge.
3751+
#else
3752+
cell->setType(PathfindCell::CELL_BRIDGE_IMPASSABLE); // it's off the bridge.
3753+
#endif
37393754
}
37403755

37413756
// check against the end lines.
@@ -3746,6 +3761,7 @@ void PathfindLayer::classifyLayerMapCell( Int i, Int j , PathfindCell *cell, Bri
37463761
cellBounds.hi.x = bottomRightCorner.x;
37473762
cellBounds.hi.y = bottomRightCorner.y;
37483763

3764+
#if RTS_GENERALS && RETAIL_COMPATIBLE_PATHFINDING
37493765
if (m_bridge->isCellOnEnd(&cellBounds)) {
37503766
cell->setType(PathfindCell::CELL_CLEAR);
37513767
}
@@ -3759,6 +3775,21 @@ void PathfindLayer::classifyLayerMapCell( Int i, Int j , PathfindCell *cell, Bri
37593775
groundCell->setConnectLayer(cell->getLayer());
37603776
}
37613777
}
3778+
#else
3779+
if (m_bridge->isCellOnSide(&cellBounds)) {
3780+
cell->setType(PathfindCell::CELL_BRIDGE_IMPASSABLE);
3781+
} else {
3782+
if (m_bridge->isCellOnEnd(&cellBounds)) {
3783+
cell->setType(PathfindCell::CELL_CLEAR);
3784+
}
3785+
if (m_bridge->isCellEntryPoint(&cellBounds)) {
3786+
cell->setType(PathfindCell::CELL_CLEAR);
3787+
cell->setConnectLayer(LAYER_GROUND);
3788+
PathfindCell *groundCell = TheAI->pathfinder()->getCell(LAYER_GROUND, i, j );
3789+
groundCell->setConnectLayer(cell->getLayer());
3790+
}
3791+
}
3792+
#endif
37623793
}
37633794
Coord3D center = topLeftCorner;
37643795
center.x += PATHFIND_CELL_SIZE/2;
@@ -3771,7 +3802,11 @@ void PathfindLayer::classifyLayerMapCell( Int i, Int j , PathfindCell *cell, Bri
37713802
if (groundHeight+LAYER_Z_CLOSE_ENOUGH_F > bridgeHeight) {
37723803
PathfindCell *groundCell = TheAI->pathfinder()->getCell(LAYER_GROUND,i, j);
37733804
if (!(groundCell->getType()==PathfindCell::CELL_OBSTACLE)) {
3805+
#if RTS_GENERALS && RETAIL_COMPATIBLE_PATHFINDING
37743806
groundCell->setType(PathfindCell::CELL_IMPASSABLE);
3807+
#else
3808+
groundCell->setType(PathfindCell::CELL_BRIDGE_IMPASSABLE);
3809+
#endif
37753810
}
37763811
}
37773812
}
@@ -3848,7 +3883,11 @@ void PathfindLayer::classifyWallMapCell( Int i, Int j , PathfindCell *cell, Obje
38483883
cell->setType(PathfindCell::CELL_CLEAR);
38493884
} else {
38503885
if (bridgeCount!=0) {
3886+
#if RTS_GENERALS && RETAIL_COMPATIBLE_PATHFINDING
38513887
cell->setType(PathfindCell::CELL_CLIFF); // it's off the bridge.
3888+
#else
3889+
cell->setType(PathfindCell::CELL_BRIDGE_IMPASSABLE); // it's off the bridge.
3890+
#endif
38523891
}
38533892

38543893
}
@@ -4038,7 +4077,9 @@ void Pathfinder::updateLayer(Object *obj, PathfindLayerEnum layer)
40384077
*/
40394078
void Pathfinder::classifyFence( Object *obj, Bool insert )
40404079
{
4080+
#if RTS_GENERALS && RETAIL_COMPATIBLE_PATHFINDING
40414081
m_zoneManager.markZonesDirty();
4082+
#endif
40424083

40434084
const Coord3D *pos = obj->getPosition();
40444085
Real angle = obj->getOrientation();
@@ -4062,6 +4103,25 @@ void Pathfinder::classifyFence( Object *obj, Bool insert )
40624103
Real tl_x = pos->x - fenceOffset*c - halfsizeY*s;
40634104
Real tl_y = pos->y + halfsizeY*c - fenceOffset*s;
40644105

4106+
#if !(RTS_GENERALS && RETAIL_COMPATIBLE_PATHFINDING)
4107+
IRegion2D cellBounds;
4108+
cellBounds.lo.x = REAL_TO_INT_FLOOR((pos->x + 0.5f)/PATHFIND_CELL_SIZE_F);
4109+
cellBounds.lo.y = REAL_TO_INT_FLOOR((pos->y + 0.5f)/PATHFIND_CELL_SIZE_F);
4110+
// TheSuperHackers @fix Mauller 16/06/2025 Fixes uninitialized variables.
4111+
#if RETAIL_COMPATIBLE_CRC
4112+
//CRCDEBUG_LOG(("Pathfinder::classifyFence - (%d,%d)", cellBounds.hi.x, cellBounds.hi.y));
4113+
4114+
// In retail, the values in the stack often look like this. We set them
4115+
// to reduce the likelihood of mismatch.
4116+
cellBounds.hi.x = 253961804;
4117+
cellBounds.hi.y = 4202797;
4118+
#else
4119+
cellBounds.hi.x = REAL_TO_INT_CEIL((pos->x + 0.5f)/PATHFIND_CELL_SIZE_F);
4120+
cellBounds.hi.y = REAL_TO_INT_CEIL((pos->y + 0.5f)/PATHFIND_CELL_SIZE_F);
4121+
#endif
4122+
Bool didAnything = false;
4123+
#endif // !(RTS_GENERALS && RETAIL_COMPATIBLE_PATHFINDING)
4124+
40654125
for (Int iy = 0; iy < numStepsY; ++iy, tl_x += ydx, tl_y += ydy)
40664126
{
40674127
Real x = tl_x;
@@ -4072,6 +4132,7 @@ void Pathfinder::classifyFence( Object *obj, Bool insert )
40724132
Int cy = REAL_TO_INT_FLOOR((y + 0.5f)/PATHFIND_CELL_SIZE_F);
40734133
if (cx >= 0 && cy >= 0 && cx < m_extent.hi.x && cy < m_extent.hi.y)
40744134
{
4135+
#if RTS_GENERALS && RETAIL_COMPATIBLE_PATHFINDING
40754136
if (insert) {
40764137
ICoord2D pos;
40774138
pos.x = cx;
@@ -4080,9 +4141,36 @@ void Pathfinder::classifyFence( Object *obj, Bool insert )
40804141
}
40814142
else
40824143
m_map[cx][cy].removeObstacle(obj);
4144+
#else
4145+
if (insert) {
4146+
ICoord2D pos;
4147+
pos.x = cx;
4148+
pos.y = cy;
4149+
if (m_map[cx][cy].setTypeAsObstacle( obj, true, pos )) {
4150+
didAnything = true;
4151+
m_map[cx][cy].setZone(PathfindZoneManager::UNINITIALIZED_ZONE);
4152+
}
4153+
}
4154+
else {
4155+
if (m_map[cx][cy].removeObstacle(obj)) {
4156+
didAnything = true;
4157+
m_map[cx][cy].setZone(PathfindZoneManager::UNINITIALIZED_ZONE);
4158+
}
4159+
}
4160+
if (cellBounds.lo.x>cx) cellBounds.lo.x = cx;
4161+
if (cellBounds.lo.y>cy) cellBounds.lo.y = cy;
4162+
if (cellBounds.hi.x<cx) cellBounds.hi.x = cx;
4163+
if (cellBounds.hi.y<cy) cellBounds.hi.y = cy;
4164+
#endif
40834165
}
40844166
}
40854167
}
4168+
#if !(RTS_GENERALS && RETAIL_COMPATIBLE_PATHFINDING)
4169+
if (didAnything) {
4170+
m_zoneManager.markZonesDirty();
4171+
m_zoneManager.updateZonesForModify(m_map, m_layers, cellBounds, m_extent);
4172+
}
4173+
#endif
40864174
}
40874175

40884176
/**
@@ -4117,6 +4205,12 @@ void Pathfinder::classifyObjectFootprint( Object *obj, Bool insert )
41174205
// Just in case, remove the object. Remove checks that the object has been added before
41184206
// removing, so it's safer to just remove it, as by the time some units "die", they've become
41194207
// lifeless immobile husks of debris, but we still need to remove them. jba.
4208+
4209+
#if !RTS_GENERALS
4210+
if ( obj->isKindOf( KINDOF_BLAST_CRATER ) ) // since these footprints are permanent, never remove them
4211+
return;
4212+
#endif
4213+
41204214
removeUnitFromPathfindMap(obj);
41214215
if (obj->isKindOf(KINDOF_WALK_ON_TOP_OF_WALL)) {
41224216
if (!m_layers[LAYER_WALL].isUnused()) {
@@ -4160,20 +4254,35 @@ void Pathfinder::classifyObjectFootprint( Object *obj, Bool insert )
41604254
return;
41614255
}
41624256

4257+
#if RTS_GENERALS
41634258
if (obj->getHeightAboveTerrain() > PATHFIND_CELL_SIZE_F) {
41644259
return; // Don't add bounds that are up in the air.
41654260
}
4261+
#else
4262+
if (obj->getHeightAboveTerrain() > PATHFIND_CELL_SIZE_F && ( ! obj->isKindOf( KINDOF_BLAST_CRATER ) ) )
4263+
{
4264+
return; // Don't add bounds that are up in the air.... unless a blast crater wants to do just that
4265+
}
4266+
#endif
41664267
internal_classifyObjectFootprint(obj, insert);
41674268
}
41684269

41694270
void Pathfinder::internal_classifyObjectFootprint( Object *obj, Bool insert )
41704271
{
4272+
const Coord3D *pos = obj->getPosition();
4273+
4274+
#if !(RTS_GENERALS && RETAIL_COMPATIBLE_PATHFINDING)
4275+
IRegion2D cellBounds;
4276+
cellBounds.lo.x = REAL_TO_INT_FLOOR((pos->x + 0.5f)/PATHFIND_CELL_SIZE_F);
4277+
cellBounds.lo.y = REAL_TO_INT_FLOOR((pos->y + 0.5f)/PATHFIND_CELL_SIZE_F);
4278+
cellBounds.hi = cellBounds.lo;
4279+
#endif
4280+
41714281
switch(obj->getGeometryInfo().getGeomType())
41724282
{
41734283
case GEOMETRY_BOX:
41744284
{
41754285
m_zoneManager.markZonesDirty();
4176-
const Coord3D *pos = obj->getPosition();
41774286
Real angle = obj->getOrientation();
41784287

41794288
Real halfsizeX = obj->getGeometryInfo().getMajorRadius();
@@ -4203,6 +4312,7 @@ void Pathfinder::internal_classifyObjectFootprint( Object *obj, Bool insert )
42034312
Int cx = REAL_TO_INT_FLOOR((x + 0.5f)/PATHFIND_CELL_SIZE_F);
42044313
Int cy = REAL_TO_INT_FLOOR((y + 0.5f)/PATHFIND_CELL_SIZE_F);
42054314

4315+
#if RTS_GENERALS && RETAIL_COMPATIBLE_PATHFINDING
42064316
if (cx >= 0 && cy >= 0 && cx < m_extent.hi.x && cy < m_extent.hi.y)
42074317
{
42084318
if (insert) {
@@ -4214,6 +4324,28 @@ void Pathfinder::internal_classifyObjectFootprint( Object *obj, Bool insert )
42144324
else
42154325
m_map[cx][cy].removeObstacle(obj);
42164326
}
4327+
#else
4328+
if (cx >= 0 && cy >= 0 && cx < m_extent.hi.x && cy < m_extent.hi.y)
4329+
{
4330+
if (insert) {
4331+
ICoord2D pos;
4332+
pos.x = cx;
4333+
pos.y = cy;
4334+
if (m_map[cx][cy].setTypeAsObstacle( obj, false, pos )) {
4335+
m_map[cx][cy].setZone(PathfindZoneManager::UNINITIALIZED_ZONE);
4336+
}
4337+
}
4338+
else {
4339+
if (m_map[cx][cy].removeObstacle(obj)) {
4340+
m_map[cx][cy].setZone(PathfindZoneManager::UNINITIALIZED_ZONE);
4341+
}
4342+
}
4343+
if (cellBounds.lo.x>cx) cellBounds.lo.x = cx;
4344+
if (cellBounds.lo.y>cy) cellBounds.lo.y = cy;
4345+
if (cellBounds.hi.x<cx) cellBounds.hi.x = cx;
4346+
if (cellBounds.hi.y<cy) cellBounds.hi.y = cy;
4347+
}
4348+
#endif
42174349
}
42184350
}
42194351
}
@@ -4227,7 +4359,6 @@ void Pathfinder::internal_classifyObjectFootprint( Object *obj, Bool insert )
42274359
/// @todo This is a very inefficient circle-rasterizer
42284360
ICoord2D topLeft, bottomRight;
42294361
Coord2D center, delta;
4230-
const Coord3D *pos = obj->getPosition();
42314362
Real radius = obj->getGeometryInfo().getMajorRadius();
42324363
Real r2, size;
42334364

@@ -4252,6 +4383,7 @@ void Pathfinder::internal_classifyObjectFootprint( Object *obj, Bool insert )
42524383

42534384
if (delta.x*delta.x + delta.y*delta.y <= r2)
42544385
{
4386+
#if RTS_GENERALS && RETAIL_COMPATIBLE_PATHFINDING
42554387
if (i >= 0 && j >= 0 && i < m_extent.hi.x && j < m_extent.hi.y)
42564388
{
42574389
if (insert) {
@@ -4263,20 +4395,54 @@ void Pathfinder::internal_classifyObjectFootprint( Object *obj, Bool insert )
42634395
else
42644396
m_map[i][j].removeObstacle( obj );
42654397
}
4398+
#else
4399+
if (i >= 0 && j >= 0 && i < m_extent.hi.x && j < m_extent.hi.y)
4400+
{
4401+
if (insert) {
4402+
ICoord2D pos;
4403+
pos.x = i;
4404+
pos.y = j;
4405+
if (m_map[i][j].setTypeAsObstacle( obj, false, pos )) {
4406+
m_map[i][j].setZone(PathfindZoneManager::UNINITIALIZED_ZONE);
4407+
}
4408+
}
4409+
else {
4410+
if (m_map[i][j].removeObstacle(obj)) {
4411+
m_map[i][j].setZone(PathfindZoneManager::UNINITIALIZED_ZONE);
4412+
}
4413+
}
4414+
if (cellBounds.lo.x>i) cellBounds.lo.x = i;
4415+
if (cellBounds.lo.y>j) cellBounds.lo.y = j;
4416+
if (cellBounds.hi.x<i) cellBounds.hi.x = i;
4417+
if (cellBounds.hi.y<j) cellBounds.hi.y = j;
4418+
}
4419+
#endif
42664420
}
42674421
}
42684422
}
42694423
}
42704424
break;
42714425
}
4426+
4427+
#if RTS_GENERALS && RETAIL_COMPATIBLE_PATHFINDING
42724428
Region2D bounds;
4273-
Int i, j;
42744429
obj->getGeometryInfo().get2DBounds(*obj->getPosition(), obj->getOrientation(), bounds);
42754430
IRegion2D cellBounds;
42764431
cellBounds.lo.x = REAL_TO_INT_FLOOR(bounds.lo.x/PATHFIND_CELL_SIZE_F)-1;
42774432
cellBounds.lo.y = REAL_TO_INT_FLOOR(bounds.lo.y/PATHFIND_CELL_SIZE_F)-1;
42784433
cellBounds.hi.x = REAL_TO_INT_CEIL(bounds.hi.x/PATHFIND_CELL_SIZE_F)+1;
42794434
cellBounds.hi.y = REAL_TO_INT_CEIL(bounds.hi.y/PATHFIND_CELL_SIZE_F)+1;
4435+
#else
4436+
m_zoneManager.updateZonesForModify(m_map, m_layers, cellBounds, m_extent);
4437+
4438+
cellBounds.lo.x -= 2;
4439+
cellBounds.lo.y -= 2;
4440+
cellBounds.hi.x += 2;
4441+
cellBounds.hi.y += 2;
4442+
#endif
4443+
4444+
Int i, j;
4445+
42804446
if (cellBounds.lo.x < m_extent.lo.x) {
42814447
cellBounds.lo.x = m_extent.lo.x;
42824448
}
@@ -4789,6 +4955,12 @@ Bool Pathfinder::checkDestination(const Object *obj, Int cellX, Int cellY, Pathf
47894955
return false;
47904956
}
47914957

4958+
#if !(RTS_GENERALS && RETAIL_COMPATIBLE_PATHFINDING)
4959+
if (IS_IMPASSABLE(cell->getType())) {
4960+
return false;
4961+
}
4962+
#endif
4963+
47924964
if (cell->getFlags() == PathfindCell::NO_UNITS) {
47934965
continue; // Nobody is here, so it's ok.
47944966
}
@@ -4919,9 +5091,11 @@ Bool Pathfinder::checkForMovement(const Object *obj, TCheckMovementInfo &info)
49195091
if (!unit->getAIUpdateInterface()) {
49205092
return false; // can't path through not-idle units.
49215093
}
5094+
#if RTS_GENERALS && RETAIL_COMPATIBLE_PATHFINDING
49225095
if (!unit->getAIUpdateInterface()->isIdle()) {
49235096
return false; // can't path through not-idle units.
49245097
}
5098+
#endif
49255099
Bool found = false;
49265100
Int k;
49275101
for (k=0; k<numAlly; k++) {

0 commit comments

Comments
 (0)