diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/LinkageNeighbourAsm.hpp b/src/OpenSHC/Map/Navigation/PathFindingState/LinkageNeighbourAsm.hpp index 0d64d55783..9320f9482d 100644 --- a/src/OpenSHC/Map/Navigation/PathFindingState/LinkageNeighbourAsm.hpp +++ b/src/OpenSHC/Map/Navigation/PathFindingState/LinkageNeighbourAsm.hpp @@ -37,8 +37,7 @@ int _tile, _cY, _cLink short _curGen, _cCardinalDistance - and takes the queue end as the WRITEIDX macro argument, which it advances. It clobbers eax, ebx, ecx, edx, esi and - edi. + and takes the queue end as the WRITEIDX macro argument, which it advances. It clobbers eax, ebx, ecx, edx, esi and edi. ID must be unique within the enclosing function; it exists only to keep the assembler labels of two expansions apart. @@ -190,10 +189,7 @@ __asm add WRITEIDX, 1 \ __asm push_done_##ID##_##N: -#define MACRO_LINKAGE_EXPAND_AREA_NEIGHBOURS(ID, WRITEIDX) \ - __asm mov edx, _tile \ - __asm mov edi, _areaLayer \ - __asm mov ebx, _cLink \ +#define MACRO_LINKAGE_AREA_PUSHES(ID, WRITEIDX) \ MACRO_LINKAGE_PUSH_AREA(ID, w, WRITEIDX, -2, 0x40, MACRO_ASM_DEC, MACRO_ASM_SAME) \ MACRO_LINKAGE_PUSH_AREA(ID, e, WRITEIDX, +2, 0x04, MACRO_ASM_INC, MACRO_ASM_SAME) \ __asm mov edx, _tile \ @@ -214,4 +210,34 @@ MACRO_LINKAGE_PUSH_AREA(ID, s, WRITEIDX, 0, 0x10, MACRO_ASM_SAME, MACRO_ASM_INC) \ MACRO_LINKAGE_PUSH_AREA(ID, se, WRITEIDX, +2, 0x08, MACRO_ASM_INC, MACRO_ASM_INC) +// The flood-fill's inner loop as the original writes it (0x00499711): the loop test, the +// zone-size counter bump and the three per-entry loads are handwritten too, and what they leave +// in edx (the tile), bl (the linkage byte) and edi (the area layer) is what the pushes consume - +// which is why those no longer reload them. Needs "int* _zoneSizes" and "uchar* _linkage" +// beside the locals the pushes use, "int _tile" and "int _cY" declared outside the loop, and +// the area id as a short, since the original keeps it in a 16-bit register. +#define MACRO_LINKAGE_AREA_LOOP(ID, READIDX, WRITEIDX) \ + __asm mov edi, _areaLayer \ + __asm area_loop_##ID: \ + __asm mov ecx, READIDX \ + __asm cmp ecx, WRITEIDX \ + __asm je area_loop_done_##ID \ + __asm mov esi, _zoneSizes \ + __asm mov eax, 0 \ + __asm mov edx, 1 \ + __asm mov ax, word ptr _areaID \ + __asm add dword ptr [esi + eax*4], edx \ + __asm mov esi, _tilesQueue \ + __asm mov edx, dword ptr [esi + ecx*4] \ + __asm mov _tile, edx \ + __asm mov esi, _yQueue \ + __asm mov eax, 0 \ + __asm mov ax, word ptr [esi + ecx*2] \ + __asm mov _cY, eax \ + __asm mov ebx, _linkage \ + __asm mov bl, byte ptr [ebx + edx] \ + MACRO_LINKAGE_AREA_PUSHES(ID, WRITEIDX) \ + __asm add READIDX, 1 \ + __asm jmp area_loop_##ID \ + __asm area_loop_done_##ID: // clang-format on diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/aggressiveStanceTargetBuildingAtRange.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/aggressiveStanceTargetBuildingAtRange.cpp new file mode 100644 index 0000000000..60d8fa5cc3 --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/aggressiveStanceTargetBuildingAtRange.cpp @@ -0,0 +1,184 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/IO/LowLevelMemory.func.hpp" +#include "OpenSHC/Map/Buildings/BuildingsState.func.hpp" +#include "OpenSHC/Game/GameMode.hpp" +#include "OpenSHC/Map/Location/Point8ShortXY.hpp" +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_GameState.hpp" +#include "OpenSHC/Globals/DAT_GameSynchronyState.hpp" +#include "OpenSHC/Globals/DAT_LowLevelMemory.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_UnitsState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + + using OpenSHC::Game::GameMode; + using OpenSHC::Map::Location::Point8ShortXY; + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + /* + WARNING: Enum "DPSEND_EnumInt": Some values do not have unique names + */ + /* + WARNING: Enum "DPERRInt": Some values do not have unique names + */ + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x004A1230 + void PathFindingState::aggressiveStanceTargetBuildingAtRange(int unitID, int maxDistance) + { + int (*paiVar4)[8]; + uint uVar5; + uint uVar7; + int _nextCandidate; + int _tile; + short sVar1 = DAT_UnitsState::instance.units[unitID].x; + uVar5 = (uint)sVar1; + short sVar2 = DAT_UnitsState::instance.units[unitID].y; + uVar7 = (uint)sVar2; + this->calculations = this->calculations + 1; + this->ALG_ResultTile = 0; + this->ALG_ResultY = 0; + this->ALG_ResultX = 0; + if (uVar5 > 399 || uVar7 > 399) { + return; + } + if (DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[uVar7 * 400 + uVar5] == '\0') { + return; + } + this->searchGeneration = this->searchGeneration + 1; + if (32000 < this->searchGeneration) { + this->searchGeneration = 1; + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 0x27420, '\0', (void*)((int)(DAT_TileMapState::instance.WalkLayer))); + } + this->searchQueue.currentDistance = 1; + this->searchQueue.writeIndex = 1; + this->searchQueue.readIndex = 0; + this->searchQueue.yQueue[0] = sVar2; + this->searchQueue.tilesQueue[0] + = DAT_ViewportRenderState::instance.translationMatrix[uVar7].addXgetTile + uVar5; + this->searchQueue.xQueue[0] = sVar1; + DAT_TileMapState::instance.CertainPathLayer[this->searchQueue.tilesQueue[0]] = 1; + DAT_TileMapState::instance.WalkLayer[this->searchQueue.tilesQueue[0]] = (short)this->searchGeneration; + if ((DAT_TileMapState::instance.LogicLayer[this->searchQueue.tilesQueue[0]] & 0x30) == 0 + && this->searchQueue.readIndex != this->searchQueue.writeIndex) { + while ((_tile = this->searchQueue.tilesQueue[this->searchQueue.readIndex], + -1 < _tile && (_tile < 0x13a10))) { + sVar1 = this->searchQueue.xQueue[this->searchQueue.readIndex]; + this->searchQueue.currentDistance = (int)DAT_TileMapState::instance.CertainPathLayer[_tile]; + sVar2 = this->searchQueue.yQueue[this->searchQueue.readIndex]; + if (0x13a10 < (int)this->searchQueue.currentDistance) { + return; + } + if ((int)this->searchQueue.currentDistance > maxDistance) { + return; + } + for (int _direction = 0; _direction < 8; _direction = _direction + 2) { + _nextCandidate + = DAT_TileMapState::instance.directionTranslationMatrix[sVar2][_direction] + _tile; + uVar5 = DAT_TileMapState::instance.LogicLayer[_nextCandidate]; + if (DAT_TileMapState::instance.WalkLayer[_nextCandidate] != this->searchGeneration) { + if (DAT_TileMapState::instance.BuildingLayer[_nextCandidate] == 0) { + /* + Is wall or gatehouseIs wall or gatehouse + */ + /* + TODO:FIXME: WallOwnerLayer contains player ids, not necessarily team ids + */ + if ((uVar5 & 0x100) != 0 + && (DAT_GameSynchronyState::instance.currentGameMode == OpenSHC::Game::GM_SOLITARY + || (DAT_GameState::instance.mapAndTime.skirmishStrongWalls == 0)) + && DAT_GameState::instance.mapAndTime + .playerTeams[(DAT_TileMapState::instance.WallOwnerLayer[_nextCandidate] & 7) + + 1] + != DAT_GameState::instance.mapAndTime + .playerTeams[DAT_UnitsState::instance.units[unitID].owner]) { + this->ALG_ResultTile = _nextCandidate; + return; + } + } else { + uVar7 = (uint)DAT_TileMapState::instance.BuildingLayer[_nextCandidate]; + if (DAT_GameState::instance.mapAndTime + .playerTeams[DAT_UnitsState::instance.units[unitID].owner] + != DAT_GameState::instance.mapAndTime + .playerTeams[DAT_BuildingsState::instance.buildings[uVar7].owner]) { + switch (DAT_BuildingsState::instance.buildings[uVar7].buildingType) { + case OpenSHC::Map::Buildings::BT_STOCKPILE: + case OpenSHC::Map::Buildings::BT_MANORHOUSE: + case OpenSHC::Map::Buildings::BT_STONEKEEP: + case OpenSHC::Map::Buildings::BT_STRONGHOLD: + case OpenSHC::Map::Buildings::BT_CAMPFIRE: + case OpenSHC::Map::Buildings::BT_SIGNPOST: + case OpenSHC::Map::Buildings::BT_PARADEGROUND: + case OpenSHC::Map::Buildings::BT_CAMPGROUND: + case OpenSHC::Map::Buildings::BT_PARADEGROUND2: + case OpenSHC::Map::Buildings::BT_PARADEGROUND3: + case OpenSHC::Map::Buildings::BT_PARADEGROUND4: + case OpenSHC::Map::Buildings::BT_PARADEGROUND5: + case OpenSHC::Map::Buildings::BT_KILLINGPIT: + case OpenSHC::Map::Buildings::BT_KEEPDOOR_LEFT: + case OpenSHC::Map::Buildings::BT_KEEPDOOR_RIGHT: + case OpenSHC::Map::Buildings::BT_KEEPDOOR: + break; + default: + BOOLEnum BVar3 = MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::getBuildingHasHealthProperty, + DAT_BuildingsState::ptr)(uVar7, _nextCandidate); + if (BVar3 != FALSE) { + this->ALG_ResultTile = _nextCandidate; + return; + } + } + } + } + if ((uVar5 & 0x30) == 0) { + /* + If not the border, enqueue next candidate + */ + DAT_TileMapState::instance.CertainPathLayer[_nextCandidate] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[_nextCandidate] = (short)this->searchGeneration; + this->searchQueue.xQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction] + .short_.xOffset + + sVar1; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction] + .short_.yOffset + + sVar2; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = _nextCandidate; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + } + } + + this->searchQueue.readIndex = this->searchQueue.readIndex + 1; + if (0x13a10 <= (int)this->searchQueue.readIndex) { + this->searchQueue.readIndex = 0; + } + if (this->searchQueue.readIndex == this->searchQueue.writeIndex) { + return; + } + } + } + return; + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/algFindAttackAngle.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/algFindAttackAngle.cpp new file mode 100644 index 0000000000..4c86b13032 --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/algFindAttackAngle.cpp @@ -0,0 +1,121 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/IO/LowLevelMemory.func.hpp" +#include "OpenSHC/Map/Units/TroopValueState.func.hpp" + +#include "OpenSHC/Globals/DAT_ClimbLogicDefinedData.hpp" +#include "OpenSHC/Globals/DAT_LowLevelMemory.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_TribesState.hpp" +#include "OpenSHC/Globals/DAT_TroopValueState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x0049F540 + int PathFindingState::algFindAttackAngle(int maxDistance200, uint x, uint y, int tribeID) + { + int _siegeIndex; + int _tile; + if (399 < x || 399 < y) { + return 0; + } + if (DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[y * 400 + x] == '\0') { + return 0; + } + this->calculations = this->calculations + 1; + this->searchGeneration = this->searchGeneration + 1; + if (32000 < this->searchGeneration) { + this->searchGeneration = 1; + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 160800, '\0', (void*)((int)(DAT_TileMapState::instance.WalkLayer))); + } + this->searchQueue.readIndex = 0; + this->searchQueue.writeIndex = 1; + this->searchQueue.currentDistance = 1; + this->searchQueue.yQueue[0] = (short)y; + this->searchQueue.xQueue[0] = (short)x; + int _startTile = DAT_ViewportRenderState::instance.translationMatrix[y].addXgetTile + x; + this->searchQueue.tilesQueue[0] = _startTile; + DAT_TileMapState::instance.CertainPathLayer[_startTile] = 1; + DAT_TileMapState::instance.WalkLayer[this->searchQueue.tilesQueue[0]] = (short)this->searchGeneration; + if (this->searchQueue.readIndex != this->searchQueue.writeIndex) { + while (true) { + int _tileOption = this->searchQueue.tilesQueue[this->searchQueue.readIndex]; + if (_tileOption < 0) { + break; + } + if (80400 <= _tileOption) { + break; + } + int _xOption = (int)this->searchQueue.xQueue[this->searchQueue.readIndex]; + int _yOption = (int)this->searchQueue.yQueue[this->searchQueue.readIndex]; + this->searchQueue.currentDistance = (int)DAT_TileMapState::instance.CertainPathLayer[_tileOption]; + if (80400 < (int)this->searchQueue.currentDistance) { + return 0; + } + if ((int)this->searchQueue.currentDistance > maxDistance200) { + return 0; + } + for (int _direction = 0; _direction < 8; _direction = _direction + 1) { + if ((DAT_TileMapState::instance.PathLinkageLayer[_tileOption] + & DAT_ClimbLogicDefinedData::instance.BitFlagHelperForPathLinkage[_direction]) + != 0 + && (_tile = DAT_TileMapState::instance.directionTranslationMatrix[_yOption][_direction] + + _tileOption, + DAT_TileMapState::instance.WalkLayer[_tile] != this->searchGeneration)) { + if (4 < (int)this->searchQueue.currentDistance + && (DAT_TileMapState::instance.AIInfoLayer[_tile] & 0x80) != 0 + && (_siegeIndex + = MACRO_CALL_MEMBER(OpenSHC::Map::Units::TroopValueState_Func::getSiegeIndexForTile, + DAT_TroopValueState::ptr)(_tile), + _siegeIndex != 0) + && _siegeIndex != DAT_TribesState::instance.tribes[tribeID].siegeIndexValue1 + && _siegeIndex != DAT_TribesState::instance.tribes[tribeID].siegeIndexValue2 + && DAT_TroopValueState::instance.attackInfo.tentPointsValues[_siegeIndex].three == 0 + && DAT_TroopValueState::instance.attackInfo.tentPointsValues[_siegeIndex].tribeID + == 0) { + return _siegeIndex; + } + DAT_TileMapState::instance.CertainPathLayer[_tile] + = (short)this->searchQueue.currentDistance + 1; + short _xOffset + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction] + .short_.xOffset; + DAT_TileMapState::instance.WalkLayer[_tile] = (short)this->searchGeneration; + this->searchQueue.xQueue[this->searchQueue.writeIndex] = _xOffset + _xOption; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction] + .short_.yOffset + + _yOption; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = _tile; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (80400 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + } + this->searchQueue.readIndex = this->searchQueue.readIndex + 1; + if (0x13a10 <= (int)this->searchQueue.readIndex) { + this->searchQueue.readIndex = 0; + } + if (this->searchQueue.readIndex == this->searchQueue.writeIndex) { + return 0; + } + } + } + return 0; + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/algTunnelerFindTarget.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/algTunnelerFindTarget.cpp new file mode 100644 index 0000000000..a31c4f7d47 --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/algTunnelerFindTarget.cpp @@ -0,0 +1,134 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/IO/LowLevelMemory.func.hpp" +#include "OpenSHC/Map/Location/Point8ShortXY.hpp" + +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_GameState.hpp" +#include "OpenSHC/Globals/DAT_LowLevelMemory.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + using OpenSHC::Map::Location::Point8ShortXY; + + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x0049B5B0 + void PathFindingState::algTunnelerFindTarget( + int playerID, int targetPlayerID, int distance, int originX, int originY) + { + int iVar4; + uint uVar5; + short* psVar6; + int iVar7; + int (*paiVar8)[8]; + this->calculations = this->calculations + 1; + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 0x27420, '\0', (void*)((int)(DAT_TileMapState::instance.CertainPathLayer))); + this->ALG_TargetTile = 0; + this->ALG_TargetY = 0; + this->ALG_TargetX = 0; + if ((uint)originX <= 399 && (uint)originY <= 399 + && DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[originY * 400 + originX] != '\0') { + this->searchGeneration = this->searchGeneration + 1; + if (32000 < this->searchGeneration) { + this->searchGeneration = 1; + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 0x27420, '\0', (void*)((int)(DAT_TileMapState::instance.WalkLayer))); + } + this->searchQueue.readIndex = 0; + this->searchQueue.writeIndex = 1; + this->searchQueue.currentDistance = 1; + this->searchQueue.yQueue[0] = (short)originY; + this->searchQueue.xQueue[0] = (short)originX; + this->searchQueue.tilesQueue[0] + = DAT_ViewportRenderState::instance.translationMatrix[originY].addXgetTile + originX; + DAT_TileMapState::instance.WalkLayer[this->searchQueue.tilesQueue[0]] = (short)this->searchGeneration; + DAT_TileMapState::instance.CertainPathLayer[this->searchQueue.tilesQueue[0]] = 1; + if (this->searchQueue.readIndex != this->searchQueue.writeIndex) { + while ((iVar4 = this->searchQueue.tilesQueue[this->searchQueue.readIndex], + -1 < iVar4 && (iVar4 < 0x13a10))) { + int sVar1 = (int)this->searchQueue.xQueue[this->searchQueue.readIndex]; + int sVar2 = (int)this->searchQueue.yQueue[this->searchQueue.readIndex]; + iVar7 = (int)sVar2; + if ((DAT_TileMapState::instance.LogicLayer[iVar4] & 0x100U) != 0 + && (DAT_TileMapState::instance.LogicLayer[iVar4] & 2U) == 0) { + uVar5 = DAT_TileMapState::instance.WallOwnerLayer[iVar4] & 7; + if (((targetPlayerID == 0) || (targetPlayerID == uVar5 + 1)) + && DAT_GameState::instance.mapAndTime.playerTeams[playerID] + != DAT_GameState::instance.mapAndTime.playerTeams[uVar5 + 1]) { + this->ALG_TargetX = (int)sVar1; + this->ALG_TargetY = iVar7; + this->ALG_TargetTile = iVar4; + return; + } + } + int sVar3 = (ushort)DAT_TileMapState::instance.BuildingLayer[iVar4]; + if (sVar3 != 0 + && (targetPlayerID == 0 + || (targetPlayerID == DAT_BuildingsState::instance.buildings[sVar3].owner)) + && DAT_GameState::instance.mapAndTime.playerTeams[playerID] + != DAT_GameState::instance.mapAndTime + .playerTeams[DAT_BuildingsState::instance.buildings[sVar3].owner]) { + this->ALG_TargetX = (int)sVar1; + this->ALG_TargetY = iVar7; + this->ALG_TargetTile = iVar4; + return; + } + this->searchQueue.currentDistance = (int)DAT_TileMapState::instance.CertainPathLayer[iVar4]; + if ((int)this->searchQueue.currentDistance > distance) { + return; + } + psVar6 = &DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[0].short_.yOffset; + paiVar8 = DAT_TileMapState::instance.directionTranslationMatrix + iVar7; + do { + iVar7 = (*paiVar8)[0] + iVar4; + uVar5 = DAT_TileMapState::instance.LogicLayer[iVar7]; + if (DAT_TileMapState::instance.WalkLayer[iVar7] != this->searchGeneration + && (uVar5 & 0xb1) == 0 && (uVar5 & 0x301000) == 0 + && (DAT_TileMapState::instance.BuildingLayer[iVar7] == 0 + || ((int)(short)DAT_BuildingsState::instance + .buildings[DAT_TileMapState::instance.BuildingLayer[iVar7]] + .buildingType + - 0x4aU + < 3)) + && (uVar5 & 0x40000000) == 0) { + DAT_TileMapState::instance.CertainPathLayer[iVar7] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[iVar7] = (short)this->searchGeneration; + this->searchQueue.xQueue[this->searchQueue.writeIndex] + = ((Point8ShortXY*)(psVar6 + -2))->xOffset + sVar1; + this->searchQueue.yQueue[this->searchQueue.writeIndex] = *psVar6 + sVar2; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = iVar7; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (80400 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + psVar6 = psVar6 + 8; + paiVar8 = (int (*)[8])(*paiVar8 + 2); + } while ((int)psVar6 < (int)&DAT_TerrainDefinedData::instance.field61_0x138); + this->searchQueue.readIndex = this->searchQueue.readIndex + 1; + if (0x13a10 <= (int)this->searchQueue.readIndex) { + this->searchQueue.readIndex = 0; + } + if (this->searchQueue.readIndex == this->searchQueue.writeIndex) { + return; + } + } + } + } + return; + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/budgetFloodFillOnCertainPathLayer.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/budgetFloodFillOnCertainPathLayer.cpp new file mode 100644 index 0000000000..543af2c569 --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/budgetFloodFillOnCertainPathLayer.cpp @@ -0,0 +1,157 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/Map/Location/Point8IntXY.hpp" + +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + using OpenSHC::Map::Location::Point8IntXY; + + /* + WARNING: Function: __alloca_probe replaced with injection: alloca_probe + */ + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x0049DDC0 + void PathFindingState::budgetFloodFillOnCertainPathLayer(uint x, uint y, int marker, int budget) + { + int iVar1; + uint _tilesQueue[1000]; + uint _xs[1000]; + uint _ys[1000]; + int _readIndex = 0; + int _writeIndex = 1; + if (x > 399 || y > 399) { + return; + } + if (DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[y * 400 + x] == '\0') { + return; + } + this->DAT_Mini_spreads = this->DAT_Mini_spreads + 1; + _ys[0] = y; + _xs[0] = x; + _tilesQueue[0] = DAT_ViewportRenderState::instance.translationMatrix[y].addXgetTile + x; + do { + uint _tile = _tilesQueue[_readIndex]; + if (0x13a0f < _tile) { + return; + } + if (_writeIndex >= budget) { + return; + } + if (999 <= _writeIndex) { + return; + } + uint _yUnk = _xs[_readIndex]; + uint _xUnk = _ys[_readIndex]; + DAT_TileMapState::instance.CertainPathLayer[_tile] = (short)marker; + for (int _direction = 0; _direction < 8; _direction = _direction + 4) { + uint _candidate = DAT_TileMapState::instance.directionTranslationMatrix[_xUnk][_direction] + _tile; + if (DAT_TileMapState::instance.WalkLayer[_candidate] == this->searchGeneration) { + if (DAT_TileMapState::instance.CertainPathLayer[_candidate] == marker) { + budget = budget + -1; + } else if (0 < DAT_TileMapState::instance.CertainPathLayer[_candidate]) { + iVar1 = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction] + .int_.xOffset; + _tilesQueue[_writeIndex] = _candidate; + _xs[_writeIndex] = iVar1 + _yUnk; + _ys[_writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction] + .int_.yOffset + + _xUnk; + _writeIndex = _writeIndex + 1; + DAT_TileMapState::instance.CertainPathLayer[_candidate] = (short)marker; + if (999 < _writeIndex) { + _writeIndex = 0; + } + } + } else { + budget = budget + -1; + } + _candidate = DAT_TileMapState::instance.directionTranslationMatrix[_xUnk][_direction + 1] + _tile; + if (DAT_TileMapState::instance.WalkLayer[_candidate] == this->searchGeneration) { + if (DAT_TileMapState::instance.CertainPathLayer[_candidate] == marker) { + budget = budget + -1; + } else if (0 < DAT_TileMapState::instance.CertainPathLayer[_candidate]) { + iVar1 = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction + 1] + .int_.xOffset; + _tilesQueue[_writeIndex] = _candidate; + _xs[_writeIndex] = iVar1 + _yUnk; + _ys[_writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction + 1] + .int_.yOffset + + _xUnk; + _writeIndex = _writeIndex + 1; + DAT_TileMapState::instance.CertainPathLayer[_candidate] = (short)marker; + if (999 < _writeIndex) { + _writeIndex = 0; + } + } + } else { + budget = budget + -1; + } + _candidate = DAT_TileMapState::instance.directionTranslationMatrix[_xUnk][_direction + 2] + _tile; + if (DAT_TileMapState::instance.WalkLayer[_candidate] == this->searchGeneration) { + if (DAT_TileMapState::instance.CertainPathLayer[_candidate] == marker) { + budget = budget + -1; + } else if (0 < DAT_TileMapState::instance.CertainPathLayer[_candidate]) { + iVar1 = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction + 2] + .int_.xOffset; + _tilesQueue[_writeIndex] = _candidate; + _xs[_writeIndex] = iVar1 + _yUnk; + _ys[_writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction + 2] + .int_.yOffset + + _xUnk; + _writeIndex = _writeIndex + 1; + DAT_TileMapState::instance.CertainPathLayer[_candidate] = (short)marker; + if (999 < _writeIndex) { + _writeIndex = 0; + } + } + } else { + budget = budget + -1; + } + _candidate = DAT_TileMapState::instance.directionTranslationMatrix[_xUnk][_direction + 3] + _tile; + if (DAT_TileMapState::instance.WalkLayer[_candidate] == this->searchGeneration) { + if (DAT_TileMapState::instance.CertainPathLayer[_candidate] == marker) { + budget = budget + -1; + } else if (0 < DAT_TileMapState::instance.CertainPathLayer[_candidate]) { + iVar1 = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction + 3] + .int_.xOffset; + _xs[_writeIndex] = iVar1 + _yUnk; + _tilesQueue[_writeIndex] = _candidate; + _ys[_writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction + 3] + .int_.yOffset + + _xUnk; + _writeIndex = _writeIndex + 1; + DAT_TileMapState::instance.CertainPathLayer[_candidate] = (short)marker; + if (999 < _writeIndex) { + _writeIndex = 0; + } + } + } else { + budget = budget + -1; + } + } + + _readIndex = _readIndex + 1; + if (999 < _readIndex) { + _readIndex = 0; + } + } while (_readIndex != _writeIndex); + return; + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/calculateCanPlayerUnitsNavigateToAreaFromArea.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/calculateCanPlayerUnitsNavigateToAreaFromArea.cpp new file mode 100644 index 0000000000..3ed0d24790 --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/calculateCanPlayerUnitsNavigateToAreaFromArea.cpp @@ -0,0 +1,299 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_GameState.hpp" +#include "OpenSHC/Globals/DAT_PathFindingState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + + /* + maybe fromArea is the third argument, and toArea is the second? decompilerscript: committed: 2025-01-30 + 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x004A5320 + int PathFindingState::calculateCanPlayerUnitsNavigateToAreaFromArea( + int playerID, dword fromArea, dword toArea, int permitClimb) + { + int iVar1; + dword dVar2; + dword dVar3; + dword dVar4; + dword adStack_960[200]; + int aiStack_640[400]; + if (fromArea != toArea) { + int iVar5 = 0; + if (toArea == 0) { + return 0; + } + if (fromArea == 0) { + return 0; + } + int iVar7 = 1; + this->DAT_Test_likely = this->DAT_Test_likely + 1; + int local_96c = 0; + int local_968 = 0; + for (iVar7 = 1; iVar7 < this->maxClimbDataCount; iVar7 = iVar7 + 1) { + if (this->climbData[iVar7].canBeUsed == 1 + && this->climbData[iVar7].isRecognizedByPathfinding != 0) { + if (this->climbData[iVar7].type == 1) { + if (permitClimb == 0) { + continue; + } + } else if (permitClimb == 2) { + continue; + } + if (playerID == 0 + || DAT_GameState::instance.mapAndTime.playerTeams[this->climbData[iVar7].owner] + == DAT_GameState::instance.mapAndTime.playerTeams[playerID] + || DAT_BuildingsState::instance.buildings[this->climbData[iVar7].buildingID].field201_0x2c6 + != 0) { + aiStack_640[local_96c * 2 + 1] = 0; + aiStack_640[local_96c * 2] = iVar7; + local_96c = local_96c + 1; + } + } + } + int iVar6 = 0; + this->field63_0xc0 = 0; + if (0 < local_96c) { + do { + iVar1 = aiStack_640[iVar6 * 2]; + if (this->climbData[iVar1].type != 1) { + dVar2 = this->climbData[iVar1].area; + if (dVar2 == toArea) { + dVar2 = this->climbData[iVar1].wallGroupAreaID; + if ((dVar2 == fromArea) + || (dVar3 = this->climbData[iVar1].buildingArea, dVar3 == fromArea)) { + return (int)(toArea); + } + adStack_960[iVar5] = dVar2; + iVar5 = iVar5 + 1; + aiStack_640[iVar6 * 2 + 1] = 1; + if (0 < (int)dVar3) { + adStack_960[iVar5] = dVar3; + iVar5 = iVar5 + 1; + } + } else { + dVar3 = this->climbData[iVar1].wallGroupAreaID; + if (dVar3 == toArea) { + if (dVar2 == fromArea) { + return (int)(toArea); + } + dVar3 = this->climbData[iVar1].buildingArea; + if (dVar3 == fromArea) { + return (int)(toArea); + } + adStack_960[iVar5] = dVar2; + aiStack_640[iVar6 * 2 + 1] = 1; + iVar5 = iVar5 + 1; + if (0 < (int)dVar3) { + adStack_960[iVar5] = dVar3; + iVar5 = iVar5 + 1; + } + } else if (this->climbData[iVar1].buildingArea == toArea) { + if (dVar2 == fromArea) { + return (int)(toArea); + } + if (dVar3 == fromArea) { + return (int)(toArea); + } + adStack_960[iVar5] = dVar2; + iVar5 = iVar5 + 1; + adStack_960[iVar5] = dVar3; + iVar5 = iVar5 + 1; + aiStack_640[iVar6 * 2 + 1] = 1; + } + } + } + iVar6 = iVar6 + 1; + } while (iVar6 < local_96c); + if (0 < iVar5) { + do { + dVar2 = adStack_960[local_968]; + local_968 = local_968 + 1; + iVar6 = 0; + do { + if ((aiStack_640[iVar6 * 2 + 1] != 1) + && (iVar1 = aiStack_640[iVar6 * 2], this->climbData[iVar1].type != 1)) { + /* + not a ladder + */ + dVar3 = this->climbData[iVar1].area; + if (dVar3 == dVar2) { + dVar3 = this->climbData[iVar1].wallGroupAreaID; + if (dVar3 == fromArea) { + return (int)(dVar2); + } + dVar4 = this->climbData[iVar1].buildingArea; + if (dVar4 == fromArea) { + return (int)(dVar2); + } + adStack_960[iVar5] = dVar3; + iVar5 = iVar5 + 1; + aiStack_640[iVar6 * 2 + 1] = 1; + if (0 < (int)dVar4) { + adStack_960[iVar5] = dVar4; + iVar5 = iVar5 + 1; + } + } else { + dVar4 = this->climbData[iVar1].wallGroupAreaID; + if (dVar4 == dVar2) { + if (dVar3 == fromArea) { + return (int)(dVar2); + } + dVar4 = this->climbData[iVar1].buildingArea; + if (dVar4 == fromArea) { + return (int)(dVar2); + } + adStack_960[iVar5] = dVar3; + aiStack_640[iVar6 * 2 + 1] = 1; + iVar5 = iVar5 + 1; + if (0 < (int)dVar4) { + adStack_960[iVar5] = dVar4; + iVar5 = iVar5 + 1; + } + } else if (this->climbData[iVar1].buildingArea == dVar2) { + if (dVar3 == fromArea) { + return (int)(dVar2); + } + if (dVar4 == fromArea) { + return (int)(dVar2); + } + adStack_960[iVar5] = dVar3; + iVar5 = iVar5 + 1; + aiStack_640[iVar6 * 2 + 1] = 1; + adStack_960[iVar5] = dVar4; + iVar5 = iVar5 + 1; + } + } + } + iVar6 = iVar6 + 1; + } while (iVar6 < local_96c); + } while (local_968 < iVar5); + } + } + iVar6 = 0; + this->field63_0xc0 = 1; + DAT_PathFindingState::instance.field50_0x98 = 1; + if (0 < local_96c) { + do { + iVar1 = aiStack_640[iVar6 * 2]; + dVar2 = this->climbData[iVar1].area; + aiStack_640[iVar6 * 2 + 1] = 0; + if (dVar2 == toArea) { + dVar2 = this->climbData[iVar1].wallGroupAreaID; + if ((dVar2 == fromArea) + || (dVar3 = this->climbData[iVar1].buildingArea, dVar3 == fromArea)) { + return (int)(toArea); + } + adStack_960[iVar5] = dVar2; + iVar5 = iVar5 + 1; + aiStack_640[iVar6 * 2 + 1] = 1; + if (0 < (int)dVar3) { + adStack_960[iVar5] = dVar3; + iVar5 = iVar5 + 1; + } + } else { + dVar3 = this->climbData[iVar1].wallGroupAreaID; + if (dVar3 == toArea) { + if (dVar2 == fromArea) { + return (int)(toArea); + } + dVar3 = this->climbData[iVar1].buildingArea; + if (dVar3 == fromArea) { + return (int)(toArea); + } + adStack_960[iVar5] = dVar2; + aiStack_640[iVar6 * 2 + 1] = 1; + iVar5 = iVar5 + 1; + if (0 < (int)dVar3) { + adStack_960[iVar5] = dVar3; + iVar5 = iVar5 + 1; + } + } else if (this->climbData[iVar1].buildingArea == toArea) { + if ((dVar2 == fromArea) || (dVar3 == fromArea)) { + return (int)(toArea); + } + adStack_960[iVar5] = dVar2; + iVar5 = iVar5 + 1; + adStack_960[iVar5] = dVar3; + iVar5 = iVar5 + 1; + aiStack_640[iVar6 * 2 + 1] = 1; + } + } + iVar6 = iVar6 + 1; + } while (iVar6 < local_96c); + } + while (local_968 < iVar5) { + dVar2 = adStack_960[local_968]; + local_968 = local_968 + 1; + iVar6 = 0; + if (0 < local_96c) { + do { + if (aiStack_640[iVar6 * 2 + 1] != 1) { + iVar1 = aiStack_640[iVar6 * 2]; + dVar3 = this->climbData[iVar1].area; + if (dVar3 == dVar2) { + dVar3 = this->climbData[iVar1].wallGroupAreaID; + if (dVar3 == fromArea) { + return (int)(dVar2); + } + dVar4 = this->climbData[iVar1].buildingArea; + if (dVar4 == fromArea) { + return (int)(dVar2); + } + adStack_960[iVar5] = dVar3; + iVar5 = iVar5 + 1; + aiStack_640[iVar6 * 2 + 1] = 1; + if (0 < (int)dVar4) { + adStack_960[iVar5] = dVar4; + iVar5 = iVar5 + 1; + } + } else { + dVar4 = this->climbData[iVar1].wallGroupAreaID; + if (dVar4 == dVar2) { + if (dVar3 == fromArea) { + return (int)(dVar2); + } + dVar4 = this->climbData[iVar1].buildingArea; + if (dVar4 == fromArea) { + return (int)(dVar2); + } + adStack_960[iVar5] = dVar3; + aiStack_640[iVar6 * 2 + 1] = 1; + iVar5 = iVar5 + 1; + if (0 < (int)dVar4) { + adStack_960[iVar5] = dVar4; + iVar5 = iVar5 + 1; + } + } else if (this->climbData[iVar1].buildingArea == dVar2) { + if (dVar3 == fromArea) { + return (int)(dVar2); + } + if (dVar4 == fromArea) { + return (int)(dVar2); + } + adStack_960[iVar5] = dVar3; + iVar5 = iVar5 + 1; + aiStack_640[iVar6 * 2 + 1] = 1; + adStack_960[iVar5] = dVar4; + iVar5 = iVar5 + 1; + } + } + } + iVar6 = iVar6 + 1; + } while (iVar6 < local_96c); + } + } + DAT_PathFindingState::instance.field50_0x98 = 0; + fromArea = 0; + } + LAB_ret: + return (int)(fromArea); + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/calculateCanReachUsingCachedAreaLogic.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/calculateCanReachUsingCachedAreaLogic.cpp new file mode 100644 index 0000000000..212204e104 --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/calculateCanReachUsingCachedAreaLogic.cpp @@ -0,0 +1,155 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x004A5B00 + BOOLEnum PathFindingState::calculateCanReachUsingCachedAreaLogic(int tile1, int tile2) + { + int iVar1; + AreaPairInt* pAVar2; + BOOLEnum BVar3; + int iVar4; + int _area1; + int _area2; + _area2 = (int)(short)DAT_TileMapState::instance.PathConnectionLayer[tile2]; + _area1 = (int)(short)DAT_TileMapState::instance.PathConnectionLayer[tile1]; + if (_area1 == _area2) { + return TRUE; + } + if ((_area1 == 0) || (_area2 == 0)) { + return FALSE; + } + if (this->field48_0x90 == 0) { + this->field48_0x90 = 1; + this->searchQueue.acceptAreaPairArray1[0].area1 = -1; + this->searchQueue.acceptAreaPairArray1[0].area2 = -1; + this->searchQueue.rejectionAreaPairArray[0].area1 = -1; + this->searchQueue.rejectionAreaPairArray[0].area2 = -1; + this->searchQueue.acceptAreaPairArray1[1].area1 = -1; + this->searchQueue.acceptAreaPairArray1[1].area2 = -1; + this->searchQueue.rejectionAreaPairArray[1].area1 = -1; + this->searchQueue.rejectionAreaPairArray[1].area2 = -1; + this->searchQueue.acceptAreaPairArray1[2].area1 = -1; + this->searchQueue.acceptAreaPairArray1[2].area2 = -1; + this->searchQueue.rejectionAreaPairArray[2].area1 = -1; + this->searchQueue.rejectionAreaPairArray[2].area2 = -1; + this->searchQueue.acceptAreaPairArray1[3].area1 = -1; + this->searchQueue.acceptAreaPairArray1[3].area2 = -1; + this->searchQueue.rejectionAreaPairArray[3].area1 = -1; + this->searchQueue.rejectionAreaPairArray[3].area2 = -1; + this->searchQueue.acceptAreaPairArray1[4].area1 = -1; + this->searchQueue.acceptAreaPairArray1[4].area2 = -1; + this->searchQueue.rejectionAreaPairArray[4].area1 = -1; + this->searchQueue.rejectionAreaPairArray[4].area2 = -1; + this->searchQueue.acceptAreaPairArray1[5].area1 = -1; + this->searchQueue.acceptAreaPairArray1[5].area2 = -1; + this->searchQueue.rejectionAreaPairArray[5].area1 = -1; + this->searchQueue.rejectionAreaPairArray[5].area2 = -1; + this->searchQueue.acceptAreaPairArray1[6].area1 = -1; + this->searchQueue.acceptAreaPairArray1[6].area2 = -1; + this->searchQueue.rejectionAreaPairArray[6].area1 = -1; + this->searchQueue.rejectionAreaPairArray[6].area2 = -1; + this->searchQueue.acceptAreaPairArray1[7].area1 = -1; + this->searchQueue.acceptAreaPairArray1[7].area2 = -1; + this->searchQueue.rejectionAreaPairArray[7].area1 = -1; + this->searchQueue.rejectionAreaPairArray[7].area2 = -1; + this->searchQueue.acceptAreaPairArray1[8].area1 = -1; + this->searchQueue.acceptAreaPairArray1[8].area2 = -1; + this->searchQueue.rejectionAreaPairArray[8].area1 = -1; + this->searchQueue.rejectionAreaPairArray[8].area2 = -1; + this->searchQueue.acceptAreaPairArray1[9].area1 = -1; + this->searchQueue.acceptAreaPairArray1[9].area2 = -1; + this->searchQueue.rejectionAreaPairArray[9].area1 = -1; + this->searchQueue.rejectionAreaPairArray[9].area2 = -1; + } else { + iVar4 = 0; + pAVar2 = this->searchQueue.acceptAreaPairArray1; + do { + iVar1 = pAVar2->area1; + if (iVar1 != -1) { + if ((iVar1 == _area1) && (pAVar2->area2 == _area2)) { + return TRUE; + } + if ((pAVar2->area2 == _area1) && (iVar1 == _area2)) { + return TRUE; + } + } + iVar4 = iVar4 + 1; + pAVar2 = pAVar2 + 1; + } while (iVar4 < 10); + iVar4 = 0; + pAVar2 = this->searchQueue.rejectionAreaPairArray; + do { + iVar1 = pAVar2->area1; + if (iVar1 != -1) { + if ((iVar1 == _area1) && (pAVar2->area2 == _area2)) { + return FALSE; + } + if ((pAVar2->area2 == _area1) && (iVar1 == _area2)) { + return FALSE; + } + } + iVar4 = iVar4 + 1; + pAVar2 = pAVar2 + 1; + } while (iVar4 < 10); + } + BVar3 = MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::PathFindingState_Func::pathFindingWithBuildingsIncluded, this)(tile1 + - DAT_ViewportRenderState::instance + .translationMatrix[( + short)DAT_ViewportRenderState::instance.tileTranslationMatrix_YComponent[tile1]] + .addXgetTile, + (uint)((short)DAT_ViewportRenderState::instance.tileTranslationMatrix_YComponent[tile1]), + (uint)(tile2 + - DAT_ViewportRenderState::instance + .translationMatrix[( + short)DAT_ViewportRenderState::instance.tileTranslationMatrix_YComponent[tile2]] + .addXgetTile), + (uint)((short)DAT_ViewportRenderState::instance.tileTranslationMatrix_YComponent[tile2]), 100000, 0); + if (BVar3 != FALSE) { + iVar4 = 0; + pAVar2 = this->searchQueue.acceptAreaPairArray1; + do { + if (pAVar2->area1 == -1) { + this->searchQueue.acceptAreaPairArray1[iVar4].area1 = _area1; + this->searchQueue.acceptAreaPairArray1[iVar4].area2 = _area2; + return TRUE; + } + iVar4 = iVar4 + 1; + pAVar2 = pAVar2 + 1; + } while (iVar4 < 10); + return TRUE; + } + iVar4 = 0; + pAVar2 = this->searchQueue.rejectionAreaPairArray; + do { + if (pAVar2->area1 == -1) { + this->searchQueue.rejectionAreaPairArray[iVar4].area1 = _area1; + this->searchQueue.rejectionAreaPairArray[iVar4].area2 = _area2; + return FALSE; + } + iVar4 = iVar4 + 1; + pAVar2 = pAVar2 + 1; + } while (iVar4 < 10); + return FALSE; + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/calculatePathKeepAndWallsGatesNotAllowed.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/calculatePathKeepAndWallsGatesNotAllowed.cpp new file mode 100644 index 0000000000..53faaee291 --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/calculatePathKeepAndWallsGatesNotAllowed.cpp @@ -0,0 +1,205 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/IO/LowLevelMemory.func.hpp" + +#include "OpenSHC/Globals/DAT_BuildingDefinedData.hpp" +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_ClimbLogicDefinedData.hpp" +#include "OpenSHC/Globals/DAT_LowLevelMemory.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x00498A40 + undefined4 PathFindingState::calculatePathKeepAndWallsGatesNotAllowed( + int x1, int y1, int x2, int y2, int maxTries) + { + uint uVar4; + if (399 < (uint)x1 || 399 < (uint)y1) { + return (undefined4)(0); + } + if (DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[y1 * 400 + x1] == '\0') { + return (undefined4)(0); + } + if (x2 == -1 + || (((uint)x2 <= 399 && ((uint)y2 <= 399)) + && (DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[y2 * 400 + x2] != '\0'))) { + this->searchGeneration = this->searchGeneration + 1; + if (32000 < this->searchGeneration) { + this->searchGeneration = 1; + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 0x27420, '\0', (void*)((int)(DAT_TileMapState::instance.WalkLayer))); + } + this->searchQueue.yQueue[0] = (short)y1; + this->searchQueue.writeIndex = 1; + this->searchQueue.readIndex = 0; + this->searchQueue.currentDistance = 1; + this->searchQueue.xQueue[0] = (short)x1; + this->searchQueue.tilesQueue[0] + = DAT_ViewportRenderState::instance.translationMatrix[y1].addXgetTile + x1; + DAT_TileMapState::instance.CertainPathLayer[this->searchQueue.tilesQueue[0]] = 1; + DAT_TileMapState::instance.WalkLayer[this->searchQueue.tilesQueue[0]] = (short)this->searchGeneration; + if (x2 == -1) { + uVar4 = 0; + } else { + uVar4 = DAT_ViewportRenderState::instance.translationMatrix[y2].addXgetTile + x2; + } + if (this->searchQueue.readIndex != this->searchQueue.writeIndex) { + while (true) { + uint _tile = this->searchQueue.tilesQueue[this->searchQueue.readIndex]; + if (_tile == uVar4) { + return (undefined4)(1); + } + if ((this->searchQueue.readIndex > maxTries) || (80400 <= _tile)) + break; + int sVar1 = (int)this->searchQueue.yQueue[this->searchQueue.readIndex]; + int sVar2 = (int)this->searchQueue.xQueue[this->searchQueue.readIndex]; + this->searchQueue.currentDistance = (int)DAT_TileMapState::instance.CertainPathLayer[_tile]; + for (int iVar3 = 0; iVar3 < 8; iVar3 = iVar3 + 4) { + int iVar6 = DAT_TileMapState::instance.directionTranslationMatrix[sVar1][iVar3] + _tile; + if (DAT_TileMapState::instance.WalkLayer[iVar6] != this->searchGeneration + && (DAT_TileMapState::instance.PathLinkageLayer[_tile] + & DAT_ClimbLogicDefinedData::instance.BitFlagHelperForPathLinkage[iVar3]) + != 0 + && (((DAT_TileMapState::instance.LogicLayer[iVar6] & 2U) != 0 + || ((DAT_TileMapState::instance.LogicLayer[iVar6] & 0x10000100U) == 0)) + || ((DAT_TileMapState::instance.BuildingLayer[iVar6] != 0 + && (DAT_BuildingDefinedData::instance + .BuildingIsGateHouseArray[(short)DAT_BuildingsState::instance + .buildings[DAT_TileMapState::instance.BuildingLayer[iVar6]] + .buildingType] + != 0))))) { + DAT_TileMapState::instance.CertainPathLayer[iVar6] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[iVar6] = (short)this->searchGeneration; + this->searchQueue.xQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[iVar3] + .short_.xOffset + + sVar2; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[iVar3] + .short_.yOffset + + sVar1; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = iVar6; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + iVar6 = DAT_TileMapState::instance.directionTranslationMatrix[sVar1][iVar3 + 1] + _tile; + if (DAT_TileMapState::instance.WalkLayer[iVar6] != this->searchGeneration + && (DAT_TileMapState::instance.PathLinkageLayer[_tile] + & DAT_ClimbLogicDefinedData::instance.BitFlagHelperForPathLinkage[iVar3 + 1]) + != 0 + && (((DAT_TileMapState::instance.LogicLayer[iVar6] & 2U) != 0 + || ((DAT_TileMapState::instance.LogicLayer[iVar6] & 0x10000100U) == 0)) + || ((DAT_TileMapState::instance.BuildingLayer[iVar6] != 0 + && (DAT_BuildingDefinedData::instance + .BuildingIsGateHouseArray[(short)DAT_BuildingsState::instance + .buildings[DAT_TileMapState::instance.BuildingLayer[iVar6]] + .buildingType] + != 0))))) { + DAT_TileMapState::instance.CertainPathLayer[iVar6] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[iVar6] = (short)this->searchGeneration; + this->searchQueue.xQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[iVar3 + 1] + .short_.xOffset + + sVar2; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[iVar3 + 1] + .short_.yOffset + + sVar1; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = iVar6; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + iVar6 = DAT_TileMapState::instance.directionTranslationMatrix[sVar1][iVar3 + 2] + _tile; + if (DAT_TileMapState::instance.WalkLayer[iVar6] != this->searchGeneration + && (DAT_TileMapState::instance.PathLinkageLayer[_tile] + & DAT_ClimbLogicDefinedData::instance.BitFlagHelperForPathLinkage[iVar3 + 2]) + != 0 + && (((DAT_TileMapState::instance.LogicLayer[iVar6] & 2U) != 0 + || ((DAT_TileMapState::instance.LogicLayer[iVar6] & 0x10000100U) == 0)) + || ((DAT_TileMapState::instance.BuildingLayer[iVar6] != 0 + && (DAT_BuildingDefinedData::instance + .BuildingIsGateHouseArray[(short)DAT_BuildingsState::instance + .buildings[DAT_TileMapState::instance.BuildingLayer[iVar6]] + .buildingType] + != 0))))) { + DAT_TileMapState::instance.CertainPathLayer[iVar6] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[iVar6] = (short)this->searchGeneration; + this->searchQueue.xQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[iVar3 + 2] + .short_.xOffset + + sVar2; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[iVar3 + 2] + .short_.yOffset + + sVar1; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = iVar6; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + iVar6 = DAT_TileMapState::instance.directionTranslationMatrix[sVar1][iVar3 + 3] + _tile; + if (DAT_TileMapState::instance.WalkLayer[iVar6] != this->searchGeneration + && (DAT_TileMapState::instance.PathLinkageLayer[_tile] + & DAT_ClimbLogicDefinedData::instance.BitFlagHelperForPathLinkage[iVar3 + 3]) + != 0 + && (((DAT_TileMapState::instance.LogicLayer[iVar6] & 2U) != 0 + || ((DAT_TileMapState::instance.LogicLayer[iVar6] & 0x10000100U) == 0)) + || ((DAT_TileMapState::instance.BuildingLayer[iVar6] != 0 + && (DAT_BuildingDefinedData::instance + .BuildingIsGateHouseArray[(short)DAT_BuildingsState::instance + .buildings[DAT_TileMapState::instance.BuildingLayer[iVar6]] + .buildingType] + != 0))))) { + DAT_TileMapState::instance.CertainPathLayer[iVar6] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[iVar6] = (short)this->searchGeneration; + this->searchQueue.xQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[iVar3 + 3] + .short_.xOffset + + sVar2; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[iVar3 + 3] + .short_.yOffset + + sVar1; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = iVar6; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + } + this->searchQueue.readIndex = this->searchQueue.readIndex + 1; + if (80400 <= (int)this->searchQueue.readIndex) { + this->searchQueue.readIndex = 0; + } + if (this->searchQueue.readIndex == this->searchQueue.writeIndex) { + return (undefined4)(0); + } + } + } + } + return (undefined4)(0); + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/canNavigateFunctionReturnsArea.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/canNavigateFunctionReturnsArea.cpp new file mode 100644 index 0000000000..654d375b13 --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/canNavigateFunctionReturnsArea.cpp @@ -0,0 +1,126 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/IO/LowLevelMemory.func.hpp" +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" + +#include "OpenSHC/Globals/DAT_LowLevelMemory.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + returns area (a value >= 1) if the unit can get there, if not, 0 decompilerscript: committed: 2025-01-30 + 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x004A6DF0 + int PathFindingState::canNavigateFunctionReturnsArea(int playerID, dword targetArea, uint unitX, uint unitY) + { + int (*paiVar5)[8]; + int iVar6; + int _area; + this->ALG_ResultTile = 0; + this->ALG_ResultY = 0; + this->ALG_ResultX = 0; + if (399 < unitX || 399 < unitY) { + return 0; + } + if (DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[unitY * 400 + unitX] == '\0') { + return 0; + } + this->searchGeneration = this->searchGeneration + 1; + if (32000 < this->searchGeneration) { + this->searchGeneration = 1; + /* + clear up the tilemap short[160800] + */ + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 160800, '\0', (void*)((int)(DAT_TileMapState::instance.WalkLayer))); + } + this->searchQueue.readIndex = 0; + this->searchQueue.writeIndex = 1; + this->searchQueue.currentDistance = 1; + this->searchQueue.yQueue[0] = (short)unitY; + this->searchQueue.xQueue[0] = (short)unitX; + int _startTile = DAT_ViewportRenderState::instance.translationMatrix[unitY].addXgetTile + unitX; + this->searchQueue.tilesQueue[0] = _startTile; + DAT_TileMapState::instance.WalkLayer[this->searchQueue.tilesQueue[0]] = (short)this->searchGeneration; + DAT_TileMapState::instance.CertainPathLayer[_startTile] = (short)this->searchQueue.currentDistance; + if (this->searchQueue.readIndex != this->searchQueue.writeIndex) { + do { + int iVar3 = this->searchQueue.tilesQueue[this->searchQueue.readIndex]; + if (iVar3 < 0) { + return 0; + } + if (80400 <= iVar3) { + return 0; + } + int sVar1 = (int)this->searchQueue.xQueue[this->searchQueue.readIndex]; + int sVar2 = (int)this->searchQueue.yQueue[this->searchQueue.readIndex]; + this->searchQueue.currentDistance = (int)DAT_TileMapState::instance.CertainPathLayer[iVar3]; + if (0x13a10 < (int)this->searchQueue.currentDistance) { + return 0; + } + iVar6 = 0; + paiVar5 = DAT_TileMapState::instance.directionTranslationMatrix + sVar2; + do { + int _tile = (*paiVar5)[0] + iVar3; + uint uVar4 = DAT_TileMapState::instance.LogicLayer[_tile]; + if (DAT_TileMapState::instance.WalkLayer[_tile] != this->searchGeneration) { + if ((uVar4 & 0x40000000) != 0) { + DAT_TileMapState::instance.CertainPathLayer[_tile] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[_tile] = (short)this->searchGeneration; + this->searchQueue.xQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[iVar6] + .short_.xOffset + + sVar1; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[iVar6] + .short_.yOffset + + sVar2; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = _tile; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + if ((uVar4 & 0x4a5014b1) == 0) { + _area = (short)DAT_TileMapState::instance.PathConnectionLayer[_tile]; + _tile = MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func:: + calculateCanPlayerUnitsNavigateToAreaFromArea, + this)(playerID, (dword)((int)((short)_area)), (dword)((int)(targetArea)), 0); + if (_tile != 0) { + this->climbX + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[iVar6] + .int_.xOffset + + (int)sVar1; + this->climbY + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[iVar6] + .int_.yOffset + + (int)sVar2; + return (int)(short)_area; + } + } + } + iVar6 = iVar6 + 1; + paiVar5 = (int (*)[8])(*paiVar5 + 1); + } while (iVar6 < 8); + this->searchQueue.readIndex = this->searchQueue.readIndex + 1; + if (0x13a10 <= (int)this->searchQueue.readIndex) { + this->searchQueue.readIndex = 0; + } + } while (this->searchQueue.readIndex != this->searchQueue.writeIndex); + } + return 0; + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/certainDamageToUnitsUnk.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/certainDamageToUnitsUnk.cpp new file mode 100644 index 0000000000..be7b139c78 --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/certainDamageToUnitsUnk.cpp @@ -0,0 +1,234 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/Audio/SFX/SFXState.func.hpp" +#include "OpenSHC/IO/LowLevelMemory.func.hpp" +#include "OpenSHC/Map/Entities/EntityState.func.hpp" +#include "OpenSHC/Random/RNG.func.hpp" +#include "OpenSHC/DE/SHCDE/eSFX.hpp" +#include "OpenSHC/Map/Entities/EntityType.hpp" +#include "OpenSHC/Map/Location/Point8ShortXY.hpp" +#include "OpenSHC/Map/Units/States/UnitState.hpp" +#include "OpenSHC/Map/Units/UnitType.hpp" + +#include "OpenSHC/Globals/DAT_EntityState.hpp" +#include "OpenSHC/Globals/DAT_GameState.hpp" +#include "OpenSHC/Globals/DAT_LowLevelMemory.hpp" +#include "OpenSHC/Globals/DAT_SFXState.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_UnitsState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" +#include "OpenSHC/Globals/SEC_RNG.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + + using OpenSHC::DE::SHCDE::eSFX; + using OpenSHC::Map::Entities::EntityType; + using OpenSHC::Map::Location::Point8ShortXY; + using OpenSHC::Map::Units::UnitType; + using OpenSHC::Map::Units::States::UnitState; + + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x004A3B20 + undefined4 PathFindingState::certainDamageToUnitsUnk( + int param_1, int param_2, int param_3, int param_4, undefined4 param_5) + { + short sVar6; + int iVar11; + this->searchGeneration = this->searchGeneration + 1; + this->calculations = this->calculations + 1; + if (32000 < this->searchGeneration) { + this->searchGeneration = 1; + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 0x27420, '\0', (void*)((int)(DAT_TileMapState::instance.WalkLayer))); + } + uint uVar7 = (short)DAT_ViewportRenderState::instance.tileTranslationMatrix_YComponent[param_1]; + int iVar9 = param_1 - DAT_ViewportRenderState::instance.translationMatrix[uVar7].addXgetTile; + int local_4 = 1; + uint uVar1 = iVar9 + 100; + if (399 < uVar1 || 399 < uVar7 + || DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[uVar7 * 400 + uVar1] == '\0') { + local_4 = -1; + } + this->searchQueue.yQueue[0] = (short)uVar7; + this->searchQueue.tilesQueue[0] = param_1; + this->searchQueue.xQueue[0] = (short)iVar9; + this->searchQueue.currentDistance = 1; + this->searchQueue.readIndex = 0; + this->searchQueue.writeIndex = 1; + DAT_TileMapState::instance.CertainPathLayer[param_1] = (short)this->searchQueue.currentDistance; + DAT_TileMapState::instance.WalkLayer[this->searchQueue.tilesQueue[0]] = (short)this->searchGeneration; + EntityType local_8 = OpenSHC::Map::Entities::ET_ARROW_AND_DEFAULT; + if ((char)param_5 == '\0') { + local_8 = OpenSHC::Map::Entities::ET_CATAPULT; + } + if (this->searchQueue.readIndex != this->searchQueue.writeIndex) { + while (uVar1 = this->searchQueue.tilesQueue[this->searchQueue.readIndex], uVar1 <= 0x13a0f) { + int sVar2 = (int)this->searchQueue.xQueue[this->searchQueue.readIndex]; + int sVar3 = (int)this->searchQueue.yQueue[this->searchQueue.readIndex]; + this->searchQueue.currentDistance = (int)DAT_TileMapState::instance.CertainPathLayer[uVar1]; + if (0x13a10 < (int)this->searchQueue.currentDistance) { + return (undefined4)(0); + } + if ((int)this->searchQueue.currentDistance > param_2) { + return (undefined4)(0); + } + int uVar4 = (short)DAT_TileMapState::instance.UnitLayer[uVar1]; + while (iVar9 = uVar4, iVar9 != 0) { + if (param_3 != 0 + && DAT_GameState::instance.mapAndTime + .playerTeams[DAT_UnitsState::instance.units[iVar9].owner] + != DAT_GameState::instance.mapAndTime.playerTeams[param_3] + && DAT_UnitsState::instance.units[iVar9].unitType != OpenSHC::Map::Units::UT_LORD) { + DAT_UnitsState::instance.units[iVar9].health + = DAT_UnitsState::instance.units[iVar9].health - param_4; + if ((DAT_UnitsState::instance.units[iVar9].health <= 0) + && (DAT_UnitsState::instance.units[iVar9].dying == 0)) { + DAT_UnitsState::instance.units[iVar9].health = 0; + DAT_UnitsState::instance.units[iVar9].dying = 1; + DAT_UnitsState::instance.units[iVar9].animationCycleNumber = 0; + if ((char)param_5 != '\0') { + DAT_UnitsState::instance.units[iVar9].state.generic + = OpenSHC::Map::Units::States::US_DEATH_01; + MACRO_CALL_MEMBER(OpenSHC::Audio::SFX::SFXState_Func::playSFXAtLocation, + DAT_SFXState::ptr)((short)DAT_UnitsState::instance.units[iVar9].x, + (short)DAT_UnitsState::instance.units[iVar9].y, + OpenSHC::DE::SHCDE::FX_DEATH_ARROW); + } else { + DAT_UnitsState::instance.units[iVar9].state.generic + = OpenSHC::Map::Units::States::US_STONE_DEATH_01; + MACRO_CALL_MEMBER(OpenSHC::Audio::SFX::SFXState_Func::playSFXAtLocation, + DAT_SFXState::ptr)((short)DAT_UnitsState::instance.units[iVar9].x, + (short)DAT_UnitsState::instance.units[iVar9].y, OpenSHC::DE::SHCDE::FX_SPLAT); + } + DAT_UnitsState::instance.units[iVar9].tunnelerFinishedDigging = 1; + } + iVar11 = DAT_UnitsState::instance.units[iVar9].maxHealth; + if (iVar11 == 0) { + sVar6 = 100; + } else { + sVar6 = (short)((DAT_UnitsState::instance.units[iVar9].health * 100) / iVar11); + } + DAT_UnitsState::instance.units[iVar9].healthPercentage = sVar6; + DAT_UnitsState::instance.units[iVar9].healthbar = sVar6 / 10; + } + uVar4 = DAT_UnitsState::instance.units[iVar9].nextUnitOnTheSameTile; + } + int _random = (int)SEC_RNG::instance.currentNumber2; + MACRO_CALL_MEMBER(OpenSHC::Random::RNG_Func::nextRandomNumber2, SEC_RNG::ptr)(); + if ((_random & 1) == 0) { + iVar11 = (int)SEC_RNG::instance.currentNumber2; + MACRO_CALL_MEMBER(OpenSHC::Random::RNG_Func::nextRandomNumber2, SEC_RNG::ptr)(); + iVar9 = sVar3 * 8; + MACRO_CALL_MEMBER(OpenSHC::Map::Entities::EntityState_Func::spawnProjectileEntity, + DAT_EntityState::ptr)(0, (undefined4)((int)(param_3)), 0, + (int)(((_random >> 4) % 0x32 + 0x32) * local_4 + sVar2 * 8), iVar9 + iVar11 % 0x32 + -0x19, + (int)(DAT_TileMapState::instance.HeightLayer[uVar1] + _random % 1000 + 500), + (int)(sVar2 * 8 + 4), iVar9 + 4, (int)(DAT_TileMapState::instance.HeightLayer[uVar1]), + local_8, 0); + } + for (int _direction = 0; _direction < 8; _direction = _direction + 4) { + iVar9 = DAT_TileMapState::instance.directionTranslationMatrix[sVar3][_direction] + uVar1; + if (DAT_TileMapState::instance.WalkLayer[iVar9] != this->searchGeneration + && (DAT_TileMapState::instance.LogicLayer[iVar9] & 0x30) == 0) { + DAT_TileMapState::instance.CertainPathLayer[iVar9] + = (ushort)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[iVar9] = (ushort)this->searchGeneration; + this->searchQueue.xQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction] + .short_.xOffset + + sVar2; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction] + .short_.yOffset + + sVar3; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = iVar9; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + iVar9 = DAT_TileMapState::instance.directionTranslationMatrix[sVar3][_direction + 1] + uVar1; + if (DAT_TileMapState::instance.WalkLayer[iVar9] != this->searchGeneration + && (DAT_TileMapState::instance.LogicLayer[iVar9] & 0x30) == 0) { + DAT_TileMapState::instance.CertainPathLayer[iVar9] + = (ushort)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[iVar9] = (ushort)this->searchGeneration; + this->searchQueue.xQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction + 1] + .short_.xOffset + + sVar2; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction + 1] + .short_.yOffset + + sVar3; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = iVar9; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + iVar9 = DAT_TileMapState::instance.directionTranslationMatrix[sVar3][_direction + 2] + uVar1; + if (DAT_TileMapState::instance.WalkLayer[iVar9] != this->searchGeneration + && (DAT_TileMapState::instance.LogicLayer[iVar9] & 0x30) == 0) { + DAT_TileMapState::instance.CertainPathLayer[iVar9] + = (ushort)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[iVar9] = (ushort)this->searchGeneration; + this->searchQueue.xQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction + 2] + .short_.xOffset + + sVar2; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction + 2] + .short_.yOffset + + sVar3; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = iVar9; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + iVar9 = DAT_TileMapState::instance.directionTranslationMatrix[sVar3][_direction + 3] + uVar1; + if (DAT_TileMapState::instance.WalkLayer[iVar9] != this->searchGeneration + && (DAT_TileMapState::instance.LogicLayer[iVar9] & 0x30) == 0) { + DAT_TileMapState::instance.CertainPathLayer[iVar9] + = (ushort)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[iVar9] = (ushort)this->searchGeneration; + this->searchQueue.xQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction + 3] + .short_.xOffset + + sVar2; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction + 3] + .short_.yOffset + + sVar3; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = iVar9; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + } + + this->searchQueue.readIndex = this->searchQueue.readIndex + 1; + if (80400 <= (int)this->searchQueue.readIndex) { + this->searchQueue.readIndex = 0; + } + if (this->searchQueue.readIndex == this->searchQueue.writeIndex) { + return (undefined4)(0); + } + } + } + return (undefined4)(0); + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/checkEnemyBuildingOrDefensiveStructureWithin12Tiles.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/checkEnemyBuildingOrDefensiveStructureWithin12Tiles.cpp new file mode 100644 index 0000000000..2dfd5ece47 --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/checkEnemyBuildingOrDefensiveStructureWithin12Tiles.cpp @@ -0,0 +1,138 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/IO/LowLevelMemory.func.hpp" +#include "OpenSHC/Map/Buildings/BuildingType.hpp" +#include "OpenSHC/Map/Buildings/BuildingTypeShort.hpp" +#include "OpenSHC/Map/Location/Point8ShortXY.hpp" +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_GameState.hpp" +#include "OpenSHC/Globals/DAT_LowLevelMemory.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + + using OpenSHC::Map::Buildings::BuildingType; + using OpenSHC::Map::Buildings::BuildingTypeShort; + using OpenSHC::Map::Location::Point8ShortXY; + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x0049DB30 + BOOLEnum PathFindingState::checkEnemyBuildingOrDefensiveStructureWithin12Tiles(int playerID, uint x, uint y) + { + int (*paiVar2)[8]; + int bVar3; + short _building; + BuildingTypeShort _buildingType; + int _tile; + int _x; + int _y; + if (399 < x || 399 < y) { + return FALSE; + } + if (DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[y * 400 + x] == '\0') { + return FALSE; + } + this->searchGeneration = this->searchGeneration + 1; + if (32000 < this->searchGeneration) { + this->searchGeneration = 1; + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 0x27420, '\0', (void*)((int)(DAT_TileMapState::instance.WalkLayer))); + } + this->searchQueue.readIndex = 0; + this->searchQueue.writeIndex = 1; + this->searchQueue.currentDistance = 1; + this->searchQueue.yQueue[0] = (short)y; + this->searchQueue.xQueue[0] = (short)x; + int _startTile = DAT_ViewportRenderState::instance.translationMatrix[y].addXgetTile + x; + this->searchQueue.tilesQueue[0] = _startTile; + bVar3 = this->searchQueue.readIndex == this->searchQueue.writeIndex; + DAT_TileMapState::instance.CertainPathLayer[_startTile] = 1; + DAT_TileMapState::instance.WalkLayer[this->searchQueue.tilesQueue[0]] = (short)this->searchGeneration; + while (true) { + if (bVar3) { + return FALSE; + } + _tile = this->searchQueue.tilesQueue[this->searchQueue.readIndex]; + if (_tile < 0) { + return FALSE; + } + if (0x13a10 <= _tile) { + return FALSE; + } + _x = (int)this->searchQueue.xQueue[this->searchQueue.readIndex]; + _y = (int)this->searchQueue.yQueue[this->searchQueue.readIndex]; + _building = DAT_TileMapState::instance.BuildingLayer[_tile]; + if (_building != 0) { + _buildingType = DAT_BuildingsState::instance.buildings[_building].buildingType; + /* + find enemy building + */ + if (_buildingType != OpenSHC::Map::Buildings::BT_PITCHDITCH + && _buildingType != OpenSHC::Map::Buildings::BT_KILLINGPIT + && DAT_GameState::instance.mapAndTime + .playerTeams[DAT_BuildingsState::instance.buildings[_building].owner] + != DAT_GameState::instance.mapAndTime.playerTeams[playerID]) { + return TRUE; + } + } + /* + find enemy wall tower or gatehouse + */ + if ((DAT_TileMapState::instance.LogicLayer[_tile] & 0x100U) != 0 + && DAT_GameState::instance.mapAndTime + .playerTeams[(DAT_TileMapState::instance.WallOwnerLayer[_tile] & 7) + 1] + != DAT_GameState::instance.mapAndTime.playerTeams[playerID]) { + return TRUE; + } + this->searchQueue.currentDistance = (int)DAT_TileMapState::instance.CertainPathLayer[_tile]; + if (0x13a10 < (int)this->searchQueue.currentDistance) { + return FALSE; + } + if (12 < (int)this->searchQueue.currentDistance) + break; + for (int _direction = 0; _direction < 8; _direction = _direction + 2) { + int _candidate = DAT_TileMapState::instance.directionTranslationMatrix[_y][_direction] + _tile; + if (DAT_TileMapState::instance.WalkLayer[_candidate] != this->searchGeneration) { + DAT_TileMapState::instance.CertainPathLayer[_candidate] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[_candidate] = (short)this->searchGeneration; + this->searchQueue.xQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction] + .short_.xOffset + + _x; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction] + .short_.yOffset + + _y; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = _candidate; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + } + + this->searchQueue.readIndex = this->searchQueue.readIndex + 1; + if (0x13a10 <= (int)this->searchQueue.readIndex) { + this->searchQueue.readIndex = 0; + } + bVar3 = this->searchQueue.readIndex == this->searchQueue.writeIndex; + } + return FALSE; + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/commitUnitPathPlanUsingWalkLayer.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/commitUnitPathPlanUsingWalkLayer.cpp new file mode 100644 index 0000000000..2cbc78f56e --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/commitUnitPathPlanUsingWalkLayer.cpp @@ -0,0 +1,282 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" + +#include "OpenSHC/Globals/DAT_PathFindingState.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" +#include "OpenSHC/Globals/SEC_RNG.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x00498FD0 + uint PathFindingState::commitUnitPathPlanUsingWalkLayer(uint param_1, int param_2, int param_3) + { + int* _ptrTranslationMatrix; + int _candidateTile; + uint uVar2; + uint _cp; + uint uVar3; + int iVar4; + uint _rng; + uint uVar5; + int iVar6; + int _direction; + uint local_24; + int _tile; + int local_14; + int _y; + int _inBounds; + uint _init_10; + int _walkLayer; + if (399 < (uint)this->unitX || 399 < (uint)this->unitY + || DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[this->unitY * 400 + this->unitX] + == '\0') { + return 0; + } + _tile = DAT_ViewportRenderState::instance.translationMatrix[this->unitY].addXgetTile + this->unitX; + _y = this->unitY; + if ((short)DAT_TileMapState::instance.PathConnectionLayer[_tile] == 0) { + return 0; + } + if (param_1 == 0) { + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::findSuitableSpawnLocationUnk, + DAT_PathFindingState::ptr)(this->unitX, this->unitY, -1, -1, 80, 0); + } else if (param_1 == 1) { + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::findSuitableSpawnLocationUnk, + DAT_PathFindingState::ptr)(this->unitX, this->unitY, -1, -1, 200, 0); + } else if (param_1 == 2) { + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::findSuitableSpawnLocationUnk, + DAT_PathFindingState::ptr)(this->unitX, this->unitY, -1, -1, 500, 0); + } else if (param_1 == 3) { + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::findSuitableSpawnLocationUnk, + DAT_PathFindingState::ptr)(this->unitX, this->unitY, -1, -1, 1000, 0); + } else { + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::findSuitableSpawnLocationUnk, + DAT_PathFindingState::ptr)(this->unitX, this->unitY, -1, -1, 2000, 0); + } + local_14 = 10; + _walkLayer = (short)DAT_TileMapState::instance.WalkLayer[_tile]; + _rng = (short)SEC_RNG::instance.currentNumber2; + this->searchQueue.pathPlanIndex = 0; + iVar6 = 10; + local_24 = 1; + _inBounds = 0; + while (true) { + while (true) { + if (_inBounds && (int)local_24 <= 1) { + return (uint)(this->searchQueue.pathPlanIndex); + } + iVar4 = 2; + param_1 = local_24; + _init_10 = local_24; + _direction = 8; + _ptrTranslationMatrix = DAT_TileMapState::instance.directionTranslationMatrix[_y] + 1; + do { + _candidateTile = (*(int (*)[8])(_ptrTranslationMatrix + -1))[0] + _tile; + if ((short)DAT_TileMapState::instance.WalkLayer[_candidateTile] == _walkLayer) { + _cp = (short)DAT_TileMapState::instance.CertainPathLayer[_candidateTile]; + if (_inBounds == 0) { + if ((_cp & 0x8000) == 0 && (uVar3 = _cp & 0x3fff, (int)_init_10 <= (int)uVar3) + && (param_3 == 0 || (uVar3 != _init_10))) { + uVar2 + = ((DAT_TileMapState::instance.RandomLayer[_candidateTile] ^ _rng) & 7) + uVar3; + uVar5 = uVar2; + if (iVar4 + -2 == iVar6) { + uVar5 = uVar2 + 1; + } + if ((int)param_1 < (int)uVar5) { + param_1 = uVar2; + _direction = iVar4 + -2; + local_24 = uVar3; + } + _rng = (int)_rng >> 1 & 0x7fffU | (_rng & 1) << 0xf; + iVar6 = local_14; + } + } else if (_inBounds == 1) { + if ((_cp & 0x4000) == 0 && (uVar3 = _cp & 0x3fff, (int)uVar3 <= (int)_init_10) + && (param_3 == 0 || (uVar3 != _init_10))) { + uVar2 + = uVar3 - ((DAT_TileMapState::instance.RandomLayer[_candidateTile] ^ _rng) & 7); + uVar5 = uVar2; + if (iVar4 + -2 == iVar6) { + uVar5 = uVar2 - 1; + } + if ((int)uVar5 < (int)param_1) { + param_1 = uVar2; + _direction = iVar4 + -2; + local_24 = uVar3; + } + _rng = (int)_rng >> 1 & 0x7fffU | (_rng & 1) << 0xf; + iVar6 = local_14; + } + } + } + _candidateTile = *_ptrTranslationMatrix + _tile; + if ((short)DAT_TileMapState::instance.WalkLayer[_candidateTile] == _walkLayer) { + _cp = (short)DAT_TileMapState::instance.CertainPathLayer[_candidateTile]; + if (_inBounds == 0) { + if ((_cp & 0x8000) == 0 && (uVar3 = _cp & 0x3fff, (int)_init_10 <= (int)uVar3) + && (param_3 == 0 || (uVar3 != _init_10))) { + uVar2 + = ((DAT_TileMapState::instance.RandomLayer[_candidateTile] ^ _rng) & 7) + uVar3; + uVar5 = uVar2; + if (iVar4 + -1 == iVar6) { + uVar5 = uVar2 + 1; + } + if ((int)param_1 < (int)uVar5) { + param_1 = uVar2; + _direction = iVar4 + -1; + local_24 = uVar3; + } + _rng = (int)_rng >> 1 & 0x7fffU | (_rng & 1) << 0xf; + iVar6 = local_14; + } + } else if (_inBounds == 1) { + if ((_cp & 0x4000) == 0 && (uVar3 = _cp & 0x3fff, (int)uVar3 <= (int)_init_10) + && (param_3 == 0 || (uVar3 != _init_10))) { + uVar2 + = uVar3 - ((DAT_TileMapState::instance.RandomLayer[_candidateTile] ^ _rng) & 7); + uVar5 = uVar2; + if (iVar4 + -1 == iVar6) { + uVar5 = uVar2 - 1; + } + if ((int)uVar5 < (int)param_1) { + param_1 = uVar2; + _direction = iVar4 + -1; + local_24 = uVar3; + } + _rng = (int)_rng >> 1 & 0x7fffU | (_rng & 1) << 0xf; + iVar6 = local_14; + } + } + } + _candidateTile = _ptrTranslationMatrix[1] + _tile; + if ((short)DAT_TileMapState::instance.WalkLayer[_candidateTile] == _walkLayer) { + _cp = (short)DAT_TileMapState::instance.CertainPathLayer[_candidateTile]; + if (_inBounds == 0) { + if ((_cp & 0x8000) == 0 && (uVar3 = _cp & 0x3fff, (int)_init_10 <= (int)uVar3) + && (param_3 == 0 || (uVar3 != _init_10))) { + uVar2 + = ((DAT_TileMapState::instance.RandomLayer[_candidateTile] ^ _rng) & 7) + uVar3; + uVar5 = uVar2; + if (iVar4 == iVar6) { + uVar5 = uVar2 + 1; + } + if ((int)param_1 < (int)uVar5) { + param_1 = uVar2; + _direction = iVar4; + local_24 = uVar3; + } + _rng = (int)_rng >> 1 & 0x7fffU | (_rng & 1) << 0xf; + } + } else if (_inBounds == 1) { + if ((_cp & 0x4000) == 0 && (uVar3 = _cp & 0x3fff, (int)uVar3 <= (int)_init_10) + && (param_3 == 0 || (uVar3 != _init_10))) { + uVar2 + = uVar3 - ((DAT_TileMapState::instance.RandomLayer[_candidateTile] ^ _rng) & 7); + uVar5 = uVar2; + if (iVar4 == iVar6) { + uVar5 = uVar2 - 1; + } + if ((int)uVar5 < (int)param_1) { + param_1 = uVar2; + _direction = iVar4; + local_24 = uVar3; + } + _rng = (int)_rng >> 1 & 0x7fffU | (_rng & 1) << 0xf; + } + } + } + _candidateTile = _ptrTranslationMatrix[2] + _tile; + if ((short)DAT_TileMapState::instance.WalkLayer[_candidateTile] == _walkLayer) { + _cp = (short)DAT_TileMapState::instance.CertainPathLayer[_candidateTile]; + if (_inBounds == 0) { + if ((_cp & 0x8000) == 0 && (uVar3 = _cp & 0x3fff, (int)_init_10 <= (int)uVar3) + && (param_3 == 0 || (uVar3 != _init_10))) { + uVar2 + = ((DAT_TileMapState::instance.RandomLayer[_candidateTile] ^ _rng) & 7) + uVar3; + uVar5 = uVar2; + if (iVar4 + 1 == iVar6) { + uVar5 = uVar2 + 1; + } + if ((int)param_1 < (int)uVar5) { + param_1 = uVar2; + _direction = iVar4 + 1; + local_24 = uVar3; + } + _rng = (int)_rng >> 1 & 0x7fffU | (_rng & 1) << 0xf; + iVar6 = local_14; + } + } else if (_inBounds == 1) { + if ((_cp & 0x4000) == 0 && (uVar3 = _cp & 0x3fff, (int)uVar3 <= (int)_init_10) + && (param_3 == 0 || (uVar3 != _init_10))) { + uVar2 + = uVar3 - ((DAT_TileMapState::instance.RandomLayer[_candidateTile] ^ _rng) & 7); + uVar5 = uVar2; + if (iVar4 + 1 == iVar6) { + uVar5 = uVar2 - 1; + } + if ((int)uVar5 < (int)param_1) { + param_1 = uVar2; + _direction = iVar4 + 1; + local_24 = uVar3; + } + _rng = (int)_rng >> 1 & 0x7fffU | (_rng & 1) << 0xf; + iVar6 = local_14; + } + } + } + _ptrTranslationMatrix = _ptrTranslationMatrix + 4; + iVar4 = iVar4 + 4; + } while (iVar4 + -2 < 8); + if (_inBounds == 0) { + DAT_TileMapState::instance.CertainPathLayer[_tile] + = DAT_TileMapState::instance.CertainPathLayer[_tile] | 0x8000; + } else { + DAT_TileMapState::instance.CertainPathLayer[_tile] + = DAT_TileMapState::instance.CertainPathLayer[_tile] | 0x4000; + } + if (_direction == 8) + break; + _tile = _tile + DAT_TileMapState::instance.directionTranslationMatrix[_y][_direction]; + _y = _y + + DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction].int_.yOffset; + if ((this->searchQueue.pathPlanIndex & 1) == 0) { + this->searchQueue.ptrPathPlan[(int)this->searchQueue.pathPlanIndex / 2] = (byte)_direction; + } else { + this->searchQueue.ptrPathPlan[(int)this->searchQueue.pathPlanIndex / 2] + = this->searchQueue.ptrPathPlan[(int)this->searchQueue.pathPlanIndex / 2] & 0xf; + this->searchQueue.ptrPathPlan[(int)this->searchQueue.pathPlanIndex / 2] + = this->searchQueue.ptrPathPlan[(int)this->searchQueue.pathPlanIndex / 2] + + (byte)_direction * '\x10'; + } + this->searchQueue.pathPlanIndex = this->searchQueue.pathPlanIndex + 1; + iVar6 = _direction; + local_14 = _direction; + if (799 < (int)this->searchQueue.pathPlanIndex) { + return (uint)(this->searchQueue.pathPlanIndex); + } + } + if (param_2 == 0) { + return (uint)(this->searchQueue.pathPlanIndex); + } + if (_inBounds) + break; + _inBounds = 1; + } + return (uint)(this->searchQueue.pathPlanIndex); + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/computeAIZoneLayer.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/computeAIZoneLayer.cpp new file mode 100644 index 0000000000..a68d79419d --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/computeAIZoneLayer.cpp @@ -0,0 +1,336 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/Map/Buildings/BuildingsState.func.hpp" +#include "OpenSHC/Map/Buildings/BuildingType.hpp" +#include "OpenSHC/Map/Buildings/BuildingTypeShort.hpp" + +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_ClimbLogicDefinedData.hpp" +#include "OpenSHC/Globals/DAT_GameState.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + + using OpenSHC::Map::Buildings::BuildingType; + using OpenSHC::Map::Buildings::BuildingTypeShort; + + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + Computes the AI Zone Layer - a flood-fill from the player's keep that marks accessible areas. This creates a + "zone of control" or "accessible territory" map for strategic AI decisions. The algorithm works in + phases: Phase 1: Flood-fill through walkable/connected areas (marks tiles with value 1) Phase 2: Expand + into surrounding tiles with weighted distances based on terrain difficulty @param this - PathFindingState + object pointer @param attackedPlayerID - The player whose keep/territory to analyze @param canReachKeep - + If non-zero, limits expansion to 2000 tiles (early termination) decompilerscript: committed: 2025-01-30 + 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x004A4470 + void PathFindingState::computeAIZoneLayer(int attackedPlayerID, int canReachKeep, int param_3) + { + int _areaID; + uint uVar1; + int _offsetTile; + int _direction; + int (*_pDirectionTranslation)[8]; + int* piVar3; + int _candidateTile; + BuildingTypeShort _buildingType; + int _candidateY; + short _directionOffset; + /* + === VALIDATE PLAYER HAS A KEEP === Only compute AI zones if the player has a keep (main castle) + */ + if (DAT_GameState::instance.playerDataArray[attackedPlayerID].keep.id != 0) { + /* + === INITIALIZE BFS STARTING FROM KEEP === + */ + this->searchQueue.currentDistance = 1; + this->searchQueue.readIndex = 0; + this->searchQueue.writeIndex = 1; + /* + Get the keep's position (specifically the campfire tile inside the keep) + */ + this->searchQueue.yQueue[0] + = (short)DAT_GameState::instance.playerDataArray[attackedPlayerID].campground.yEntry; + this->searchQueue.tilesQueue[0] + = DAT_GameState::instance.playerDataArray[attackedPlayerID].campground.xEntry + + DAT_ViewportRenderState::instance + .translationMatrix[DAT_GameState::instance.playerDataArray[attackedPlayerID] + .campground.yEntry] + .addXgetTile; + /* + Mark the keep tile as AI Zone with value 1 (the starting point) + */ + DAT_TileMapState::instance.AIZoneLayer[this->searchQueue.tilesQueue[0]] + = (byte)this->searchQueue.currentDistance; + /* + Repurpose variable as iteration counter + */ + attackedPlayerID = 0; + /* + Update path linkage (possibly opens gates or updates navigation mesh) + */ + MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::updatePathLinkageTileMap, DAT_BuildingsState::ptr)(1); + /* + === PHASE 1: FLOOD-FILL THROUGH WALKABLE/CONNECTED AREAS === This phase marks all tiles that + are directly connected via normal pathfinding + */ + while (this->searchQueue.readIndex != this->searchQueue.writeIndex) { + /* + Save iteration counter + */ + int iVar2 = attackedPlayerID; + /* + === INNER LOOP: EXPAND THROUGH CONNECTED TILES === + */ + this->searchQueue.previousReadIndex = this->searchQueue.readIndex; + while (this->searchQueue.readIndex != this->searchQueue.writeIndex) { + /* + Get current tile being processed + */ + _candidateY = (int)this->searchQueue.yQueue[this->searchQueue.readIndex]; + _candidateTile = this->searchQueue.tilesQueue[this->searchQueue.readIndex]; + /* + Check all 8 adjacent directions + */ + _direction = 0; + _pDirectionTranslation = DAT_TileMapState::instance.directionTranslationMatrix + _candidateY; + do { + _offsetTile = (*_pDirectionTranslation)[0] + _candidateTile; + /* + Add tile to AI zone if: 1. Not already marked (< 1) 2. Has path connection + (PathConnectionLayer != 0) 3. Either: a) Normal pathfinding allows movement in + this direction, OR b) There's a gate (GATEHOUSELARGE or GATEHOUSESMALL) on the + tile + */ + if ((char)DAT_TileMapState::instance.AIZoneLayer[_offsetTile] <= '\0' + && (_areaID = (short)DAT_TileMapState::instance.PathConnectionLayer[_offsetTile], + _areaID != 0) + && ((DAT_TileMapState::instance.PathLinkageLayer[_candidateTile] + & DAT_ClimbLogicDefinedData::instance.BitFlagHelperForPathLinkage[_direction]) + != 0 + || ((DAT_TileMapState::instance.BuildingLayer[_offsetTile] != 0 + && ((_buildingType = DAT_BuildingsState::instance + .buildings[DAT_TileMapState::instance.BuildingLayer[_offsetTile]] + .buildingType, + _buildingType == OpenSHC::Map::Buildings::BT_GATEHOUSELARGE + || (_buildingType == OpenSHC::Map::Buildings::BT_GATEHOUSESMALL))))))) { + /* + Calculate Y offset for this direction + */ + _directionOffset + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction] + .short_.yOffset; + /* + Mark tile as part of AI zone (value 1 = directly accessible) + */ + DAT_TileMapState::instance.AIZoneLayer[_offsetTile] = 1; + /* + Add to BFS queue for further expansion + */ + this->searchQueue.yQueue[this->searchQueue.writeIndex] = _directionOffset + _candidateY; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = _offsetTile; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (80400 <= (int)this->searchQueue.writeIndex) + goto LAB_004a4914; + } + _direction = _direction + 1; + _pDirectionTranslation = (int (*)[8])(*_pDirectionTranslation + 1); + } while (_direction < 8); + /* + Move to next tile in queue + */ + this->searchQueue.readIndex = this->searchQueue.readIndex + 1; + if (80400 <= (int)this->searchQueue.readIndex) { + this->searchQueue.readIndex = 0; + } + /* + === EARLY TERMINATION CONDITIONS === If canReachKeep is set and we've marked > 2000 + tiles, stop OR if we've marked > 6000 tiles total, stop (Performance optimization + to prevent excessive computation) + */ + if (((canReachKeep != 0) && (1999 < this->searchQueue.writeIndex)) + || 5999 < this->searchQueue.writeIndex) + goto LAB_004a4914; + } + /* + === PHASE 2: EXPAND INTO DIFFICULT TERRAIN === After marking all easily accessible tiles, + expand into harder-to-reach areas with distance penalties based on terrain type + */ + this->searchQueue.readIndex = this->searchQueue.previousReadIndex; + this->searchQueue.nextWriteIndex = this->searchQueue.writeIndex; + if (this->searchQueue.previousReadIndex != this->searchQueue.writeIndex) { + do { + _direction = this->searchQueue.tilesQueue[this->searchQueue.readIndex]; + /* + Distance = current tile's AI zone value + 1 + */ + this->searchQueue.currentDistance + = (char)DAT_TileMapState::instance.AIZoneLayer[_direction] + 1; + /* + Get movement direction offsets + */ + piVar3 + = DAT_TileMapState::instance + .directionTranslationMatrix[this->searchQueue.yQueue[this->searchQueue.readIndex]] + + 1; + /* + Process tiles in groups of 4 (unrolled loop) === PROCESS ADJACENT TILES (Unrolled + loop for 4 directions at a time) === + */ + attackedPlayerID = 2; + do { + /* + === TILE 1 === + */ + _offsetTile = (*(int (*)[8])(piVar3 + -1))[0] + _direction; + /* + Only process if: 1. Not already marked 2. No blocking terrain (0x31 = sea, + cliff, or border) 3. Either no building OR building allows passage (unknownFlag4 + == 0) + */ + if ((char)DAT_TileMapState::instance.AIZoneLayer[_offsetTile] <= '\0' + && (uVar1 = DAT_TileMapState::instance.LogicLayer[_offsetTile], (uVar1 & 0x31) == 0) + && (DAT_TileMapState::instance.BuildingLayer[_offsetTile] == 0 + || (DAT_BuildingsState::instance + .buildings[DAT_TileMapState::instance.BuildingLayer[_offsetTile]] + .unknownFlag4 + == '\0'))) { + /* + === TERRAIN-BASED DISTANCE CALCULATION === + */ + if ((uVar1 & 0x100) == 0) { + /* + Non wall Non gatehouse + */ + if ((uVar1 & 0x40000000) == 0 || iVar2 == 0) { + /* + Non moat or + */ + DAT_TileMapState::instance.AIZoneLayer[_offsetTile] + = (byte)this->searchQueue.currentDistance; + } else { + /* + Moat discount making fortified areas closer in AI Zone calculations + */ + DAT_TileMapState::instance.AIZoneLayer[_offsetTile] + = (byte)this->searchQueue.currentDistance - 1; + } + } else { + /* + wall or gatehouse This makes walls, towers, and gatehouses "farther" + strategically + */ + DAT_TileMapState::instance.AIZoneLayer[_offsetTile] + = (byte)this->searchQueue.currentDistance + 6; + } + } + /* + === TILE 2 (same logic as tile 1) === + */ + _offsetTile = *piVar3 + _direction; + if ((char)DAT_TileMapState::instance.AIZoneLayer[_offsetTile] <= '\0' + && (uVar1 = DAT_TileMapState::instance.LogicLayer[_offsetTile], (uVar1 & 0x31) == 0) + && (DAT_TileMapState::instance.BuildingLayer[_offsetTile] == 0 + || (DAT_BuildingsState::instance + .buildings[DAT_TileMapState::instance.BuildingLayer[_offsetTile]] + .unknownFlag4 + == '\0'))) { + if ((uVar1 & 0x100) == 0) { + if ((uVar1 & 0x40000000) == 0 || iVar2 == 0) { + DAT_TileMapState::instance.AIZoneLayer[_offsetTile] + = (byte)this->searchQueue.currentDistance; + } else { + DAT_TileMapState::instance.AIZoneLayer[_offsetTile] + = (byte)this->searchQueue.currentDistance - 1; + } + } else { + DAT_TileMapState::instance.AIZoneLayer[_offsetTile] + = (byte)this->searchQueue.currentDistance + 6; + } + } + /* + === TILE 3 (same logic as tile 1) === + */ + _offsetTile = piVar3[1] + _direction; + if ((char)DAT_TileMapState::instance.AIZoneLayer[_offsetTile] <= '\0' + && (uVar1 = DAT_TileMapState::instance.LogicLayer[_offsetTile], (uVar1 & 0x31) == 0) + && (DAT_TileMapState::instance.BuildingLayer[_offsetTile] == 0 + || (DAT_BuildingsState::instance + .buildings[DAT_TileMapState::instance.BuildingLayer[_offsetTile]] + .unknownFlag4 + == '\0'))) { + if ((uVar1 & 0x100) == 0) { + if ((uVar1 & 0x40000000) == 0 || iVar2 == 0) { + DAT_TileMapState::instance.AIZoneLayer[_offsetTile] + = (byte)this->searchQueue.currentDistance; + } else { + DAT_TileMapState::instance.AIZoneLayer[_offsetTile] + = (byte)this->searchQueue.currentDistance - 1; + } + } else { + DAT_TileMapState::instance.AIZoneLayer[_offsetTile] + = (byte)this->searchQueue.currentDistance + 6; + } + } + /* + === TILE 4 (same logic as tile 1) === + */ + _offsetTile = piVar3[2] + _direction; + if ((char)DAT_TileMapState::instance.AIZoneLayer[_offsetTile] <= '\0' + && (uVar1 = DAT_TileMapState::instance.LogicLayer[_offsetTile], (uVar1 & 0x31) == 0) + && (DAT_TileMapState::instance.BuildingLayer[_offsetTile] == 0 + || (DAT_BuildingsState::instance + .buildings[DAT_TileMapState::instance.BuildingLayer[_offsetTile]] + .unknownFlag4 + == '\0'))) { + if ((uVar1 & 0x100) == 0) { + if ((uVar1 & 0x40000000) == 0 || iVar2 == 0) { + DAT_TileMapState::instance.AIZoneLayer[_offsetTile] + = (byte)this->searchQueue.currentDistance; + } else { + DAT_TileMapState::instance.AIZoneLayer[_offsetTile] + = (byte)this->searchQueue.currentDistance - 1; + } + } else { + DAT_TileMapState::instance.AIZoneLayer[_offsetTile] + = (byte)this->searchQueue.currentDistance + 6; + } + } + piVar3 = piVar3 + 4; + attackedPlayerID = attackedPlayerID + -1; + } while (attackedPlayerID != 0); + /* + Move to next tile in queue + */ + this->searchQueue.readIndex = this->searchQueue.readIndex + 1; + if (0x13a10 <= (int)this->searchQueue.readIndex) { + this->searchQueue.readIndex = 0; + } + } while (this->searchQueue.readIndex != this->searchQueue.nextWriteIndex); + } + /* + Increment iteration counter (alternates between 0 and 1) + */ + attackedPlayerID = iVar2 + 1; + if (1 < attackedPlayerID) { + attackedPlayerID = 0; + } + } + LAB_004a4914: + MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::updatePathLinkageTileMap, DAT_BuildingsState::ptr)(0); + } + return; + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/computeAttackVectorsBasedOnXAndY.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/computeAttackVectorsBasedOnXAndY.cpp index 9bc5c4a601..950ebef199 100644 --- a/src/OpenSHC/Map/Navigation/PathFindingState/computeAttackVectorsBasedOnXAndY.cpp +++ b/src/OpenSHC/Map/Navigation/PathFindingState/computeAttackVectorsBasedOnXAndY.cpp @@ -1,5 +1,7 @@ #include "../PathFindingState.func.hpp" +#include "OpenSHC/Map/MapConstants.hpp" + #include "OpenSHC/Globals/DAT_GameState.hpp" #include "OpenSHC/Globals/DAT_TileMapState.hpp" #include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/computeNextRallyPointDestination.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/computeNextRallyPointDestination.cpp new file mode 100644 index 0000000000..3d8dbfc61c --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/computeNextRallyPointDestination.cpp @@ -0,0 +1,119 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/IO/LowLevelMemory.func.hpp" +#include "OpenSHC/Map/Location/Point8ShortXY.hpp" + +#include "OpenSHC/Globals/DAT_LowLevelMemory.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + using OpenSHC::Map::Location::Point8ShortXY; + + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x0049CB00 + void PathFindingState::computeNextRallyPointDestination(int unitID, int xPos, int yPos) + { + int (*_cY2)[8]; + int _cTile; + short _cX; + short _cY; + this->calculations = this->calculations + 1; + this->ALG_ResultTile = 0; + this->ALG_ResultY = 0; + this->ALG_ResultX = 0; + if ((uint)xPos <= 399 && (uint)yPos <= 399 + && DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[yPos * 400 + xPos] != '\0') { + this->searchGeneration = this->searchGeneration + 1; + if (32000 < this->searchGeneration) { + this->searchGeneration = 1; + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 0x27420, '\0', (void*)((int)(DAT_TileMapState::instance.WalkLayer))); + } + this->searchQueue.readIndex = 0; + this->searchQueue.writeIndex = 1; + this->searchQueue.currentDistance = 1; + this->searchQueue.yQueue[0] = (short)yPos; + this->searchQueue.xQueue[0] = (short)xPos; + this->searchQueue.tilesQueue[0] + = DAT_ViewportRenderState::instance.translationMatrix[yPos].addXgetTile + xPos; + DAT_TileMapState::instance.WalkLayer[this->searchQueue.tilesQueue[0]] = (short)this->searchGeneration; + DAT_TileMapState::instance.CertainPathLayer[this->searchQueue.tilesQueue[0]] = 1; + if (this->searchQueue.readIndex != this->searchQueue.writeIndex) { + while ((_cTile = this->searchQueue.tilesQueue[this->searchQueue.readIndex], + -1 < _cTile && (_cTile < 0x13a10))) { + _cX = this->searchQueue.xQueue[this->searchQueue.readIndex]; + _cY = this->searchQueue.yQueue[this->searchQueue.readIndex]; + int _cY_2 = (int)_cY; + if ((short)DAT_TileMapState::instance.UnitLayer[_cTile] == unitID) { + this->ALG_ResultX = (int)_cX; + this->ALG_ResultY = _cY_2; + this->ALG_ResultTile = _cTile; + return; + } + if (DAT_TileMapState::instance.OccupancyLayer[_cTile] == '\0' + && (short)DAT_TileMapState::instance.UnitLayer[_cTile] == 0) { + this->ALG_ResultX = (int)_cX; + this->ALG_ResultY = _cY_2; + this->ALG_ResultTile = _cTile; + return; + } + this->searchQueue.currentDistance = (int)DAT_TileMapState::instance.CertainPathLayer[_cTile]; + if (0x13a10 < (int)this->searchQueue.currentDistance) { + return; + } + for (int _direction = 0; _direction < 8; _direction = _direction + 2) { + int _cTile2 + = DAT_TileMapState::instance.directionTranslationMatrix[_cY_2][_direction] + _cTile; + /* + 0xb1 == test against sea, rocky, and borders + */ + /* + 0x10001400 == test against building tree keep + */ + if (DAT_TileMapState::instance.WalkLayer[_cTile2] != this->searchGeneration + && (DAT_TileMapState::instance.LogicLayer[_cTile2] & 0xb1U) == 0 + && (DAT_TileMapState::instance.LogicLayer[_cTile2] & 0x10001400U) == 0) { + DAT_TileMapState::instance.CertainPathLayer[_cTile2] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[_cTile2] = (short)this->searchGeneration; + this->searchQueue.xQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction] + .short_.xOffset + + _cX; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction] + .short_.yOffset + + _cY; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = _cTile2; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + } + + this->searchQueue.readIndex = this->searchQueue.readIndex + 1; + if (0x13a10 <= (int)this->searchQueue.readIndex) { + this->searchQueue.readIndex = 0; + } + if (this->searchQueue.readIndex == this->searchQueue.writeIndex) { + return; + } + } + } + } + return; + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/computeTotalUnitsWithinDistance.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/computeTotalUnitsWithinDistance.cpp new file mode 100644 index 0000000000..cfc6fae0f2 --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/computeTotalUnitsWithinDistance.cpp @@ -0,0 +1,181 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/IO/LowLevelMemory.func.hpp" +#include "OpenSHC/Map/Units/TroopValueState.func.hpp" + +#include "OpenSHC/Globals/DAT_ClimbLogicDefinedData.hpp" +#include "OpenSHC/Globals/DAT_GameState.hpp" +#include "OpenSHC/Globals/DAT_LowLevelMemory.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_TroopValueState.hpp" +#include "OpenSHC/Globals/DAT_UnitsState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x0049C690 + void PathFindingState::computeTotalUnitsWithinDistance( + int playerID, int sameTeamUnits, int someLogicalTileProperty, int tile, int distance) + { + uint uVar4; + int iVar5; + int iVar6; + this->calculations = this->calculations + 1; + this->searchGeneration = this->searchGeneration + 1; + this->ALGO_TotalTroopValue = 0; + this->ALGO_TotalTroopCount = 0; + this->field34_0x64 = 0; + if (32000 < this->searchGeneration) { + this->searchGeneration = 1; + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 0x27420, '\0', (void*)((int)(DAT_TileMapState::instance.WalkLayer))); + } + this->searchQueue.readIndex = 0; + this->searchQueue.writeIndex = 1; + this->searchQueue.currentDistance = 1; + this->searchQueue.yQueue[0] + = (short)DAT_ViewportRenderState::instance.tileTranslationMatrix_YComponent[tile]; + this->searchQueue.tilesQueue[0] = tile; + DAT_TileMapState::instance.WalkLayer[this->searchQueue.tilesQueue[0]] = (short)this->searchGeneration; + DAT_TileMapState::instance.CertainPathLayer[tile] = 1; + if (this->searchQueue.readIndex != this->searchQueue.writeIndex) { + while (uVar4 = this->searchQueue.tilesQueue[this->searchQueue.readIndex], uVar4 <= 0x13a0f) { + int sVar3 = (int)this->searchQueue.yQueue[this->searchQueue.readIndex]; + int uVar2 = (short)DAT_TileMapState::instance.UnitLayer[uVar4]; + while (iVar6 = (int)(short)uVar2, iVar6 != 0) { + if (sameTeamUnits == 1) { + if (DAT_GameState::instance.mapAndTime.playerTeams[playerID] + == DAT_GameState::instance.mapAndTime + .playerTeams[DAT_UnitsState::instance.units[iVar6].owner]) { + LAB_0049c7ba: + if ((DAT_UnitsState::instance.units[iVar6].owner != 0) + && (DAT_UnitsState::instance.units[iVar6].dying == 0)) { + iVar5 = MACRO_CALL_MEMBER( + OpenSHC::Map::Units::TroopValueState_Func::getValueOfTroopType, + DAT_TroopValueState::ptr)( + (OpenSHC::Map::Units::UnitType)(int)(short)DAT_UnitsState::instance.units[iVar6] + .unitType); + this->ALGO_TotalTroopValue = this->ALGO_TotalTroopValue + iVar5; + this->ALGO_TotalTroopCount = this->ALGO_TotalTroopCount + 1; + if (this->field34_0x64 == 0) { + this->field34_0x64 = iVar6; + } + } + } + } else if ((sameTeamUnits != 0) + || (DAT_GameState::instance.mapAndTime.playerTeams[playerID] + != DAT_GameState::instance.mapAndTime + .playerTeams[DAT_UnitsState::instance.units[iVar6].owner])) + goto LAB_0049c7ba; + uVar2 = DAT_UnitsState::instance.units[iVar6].nextUnitOnTheSameTile; + } + this->searchQueue.currentDistance = (int)DAT_TileMapState::instance.CertainPathLayer[uVar4]; + if (0x13a10 < (int)this->searchQueue.currentDistance) { + return; + } + if ((int)this->searchQueue.currentDistance > distance) { + return; + } + byte bVar1 = DAT_TileMapState::instance.PathLinkageLayer[uVar4]; + for (int iVar6 = 0; iVar6 < 8; iVar6 = iVar6 + 4) { + iVar5 = DAT_TileMapState::instance.directionTranslationMatrix[sVar3][iVar6] + uVar4; + if (DAT_TileMapState::instance.WalkLayer[iVar5] != this->searchGeneration) { + if ((someLogicalTileProperty == 0 && (DAT_TileMapState::instance.LogicLayer[iVar5] & 0x30) == 0) + || (someLogicalTileProperty != 0 + && (DAT_ClimbLogicDefinedData::instance.BitFlagHelperForPathLinkage[iVar6] & bVar1) != 0)) { + DAT_TileMapState::instance.CertainPathLayer[iVar5] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[iVar5] = (short)this->searchGeneration; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[iVar6] + .short_.yOffset + + sVar3; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = iVar5; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (80400 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + } + iVar5 = DAT_TileMapState::instance.directionTranslationMatrix[sVar3][iVar6 + 1] + uVar4; + if (DAT_TileMapState::instance.WalkLayer[iVar5] != this->searchGeneration) { + if ((someLogicalTileProperty == 0 && (DAT_TileMapState::instance.LogicLayer[iVar5] & 0x30) == 0) + || (someLogicalTileProperty != 0 + && (DAT_ClimbLogicDefinedData::instance.BitFlagHelperForPathLinkage[iVar6 + 1] & bVar1) != 0)) { + DAT_TileMapState::instance.CertainPathLayer[iVar5] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[iVar5] = (short)this->searchGeneration; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[iVar6 + 1] + .short_.yOffset + + sVar3; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = iVar5; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + } + iVar5 = DAT_TileMapState::instance.directionTranslationMatrix[sVar3][iVar6 + 2] + uVar4; + if (DAT_TileMapState::instance.WalkLayer[iVar5] != this->searchGeneration) { + if ((someLogicalTileProperty == 0 && (DAT_TileMapState::instance.LogicLayer[iVar5] & 0x30) == 0) + || (someLogicalTileProperty != 0 + && (DAT_ClimbLogicDefinedData::instance.BitFlagHelperForPathLinkage[iVar6 + 2] & bVar1) != 0)) { + DAT_TileMapState::instance.CertainPathLayer[iVar5] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[iVar5] = (short)this->searchGeneration; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[iVar6 + 2] + .short_.yOffset + + sVar3; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = iVar5; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + } + iVar5 = DAT_TileMapState::instance.directionTranslationMatrix[sVar3][iVar6 + 3] + uVar4; + if (DAT_TileMapState::instance.WalkLayer[iVar5] != this->searchGeneration) { + if ((someLogicalTileProperty == 0 && (DAT_TileMapState::instance.LogicLayer[iVar5] & 0x30) == 0) + || (someLogicalTileProperty != 0 + && (DAT_ClimbLogicDefinedData::instance.BitFlagHelperForPathLinkage[iVar6 + 3] & bVar1) != 0)) { + DAT_TileMapState::instance.CertainPathLayer[iVar5] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[iVar5] = (short)this->searchGeneration; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[iVar6 + 3] + .short_.yOffset + + sVar3; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = iVar5; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + } + } + this->searchQueue.readIndex = this->searchQueue.readIndex + 1; + if (0x13a10 <= (int)this->searchQueue.readIndex) { + this->searchQueue.readIndex = 0; + } + if (this->searchQueue.readIndex == this->searchQueue.writeIndex) { + return; + } + } + } + return; + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/createClimbData.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/createClimbData.cpp new file mode 100644 index 0000000000..dada5f6eda --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/createClimbData.cpp @@ -0,0 +1,77 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" + +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_GameCore.hpp" +#include "OpenSHC/Globals/DAT_UnitsState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + + /* + @param size meaning width of climb area, e.g. gate small has 3, gate large has 4 (why not 5?), ladder has 1 + decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x004A9510 + int PathFindingState::createClimbData(int size, int buildingID, int unitID, int direction, int param_5) + { + ClimbData* pCVar1; + int _climbID; + _climbID = 1; + pCVar1 = this->climbData + 1; + while (pCVar1->canBeUsed != 0) { + _climbID = _climbID + 1; + pCVar1 = pCVar1 + 1; + if (200 <= _climbID) { + return 0; + } + } + this->climbData[_climbID].canBeUsed = 1; + this->climbData[_climbID].type = size; + this->climbData[_climbID].isRecognizedByPathfinding = 0; + this->climbData[_climbID].climbDataRelated = DAT_GameCore::instance.uniqueGameObjectTracker; + DAT_GameCore::instance.uniqueGameObjectTracker = DAT_GameCore::instance.uniqueGameObjectTracker + 1; + this->climbData[_climbID].buildingID = buildingID; + this->climbData[_climbID].unitID = unitID; + if (buildingID != 0) { + /* + buildingID != 0 + */ + this->climbData[_climbID].sourceUID = DAT_BuildingsState::instance.buildings[buildingID].uid; + this->climbData[_climbID].owner = (int)DAT_BuildingsState::instance.buildings[buildingID].owner; + this->climbData[_climbID].bottomXPosition + = (int)(short)DAT_BuildingsState::instance.buildings[buildingID].x; + this->climbData[_climbID].bottomYPosition + = (int)(short)DAT_BuildingsState::instance.buildings[buildingID].y; + this->climbData[_climbID].bottomTilePosition + = DAT_BuildingsState::instance.buildings[buildingID].currentTilePositionAdjusted; + if (size == 6 || size == 4) { + this->climbData[_climbID].ladderDirection = direction; + return _climbID; + } + if (size == 5 || size == 3) { + this->climbData[_climbID].ladderDirection = direction; + } + return _climbID; + } + if (unitID == 0) { + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::clearClimbData, this)(_climbID); + return _climbID; + } + /* + unitID != 0 + */ + this->climbData[_climbID].sourceUID = DAT_UnitsState::instance.units[unitID].uid; + this->climbData[_climbID].owner = (int)DAT_UnitsState::instance.units[unitID].owner; + this->climbData[_climbID].bottomXPosition = (int)DAT_UnitsState::instance.units[unitID].x; + this->climbData[_climbID].bottomYPosition = (int)DAT_UnitsState::instance.units[unitID].y; + this->climbData[_climbID].bottomTilePosition = DAT_UnitsState::instance.units[unitID].tile; + DAT_UnitsState::instance.units[unitID].wallDataID = (short)_climbID; + return _climbID; + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/doMoveFromTileToTile.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/doMoveFromTileToTile.cpp new file mode 100644 index 0000000000..6fa4d5e836 --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/doMoveFromTileToTile.cpp @@ -0,0 +1,138 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/Map/Entities/EntityType.hpp" +#include "OpenSHC/Map/Units/States/UnitState.hpp" +#include "OpenSHC/Map/Units/UnitType.hpp" +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +#include "OpenSHC/Globals/DAT_ClimbLogicDefinedData.hpp" +#include "OpenSHC/Globals/DAT_EntityState.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_UnitsState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + + using OpenSHC::Map::Entities::EntityType; + using OpenSHC::Map::Units::UnitType; + using OpenSHC::Map::Units::States::UnitState; + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x00497280 + BOOLEnum PathFindingState::doMoveFromTileToTile( + int unitID, int tile, int y, int direction, int param_5, int ignoreAssassinClimbing) + { + uint uVar3; + uint uVar4; + if (param_5 == 0) { + /* + if we cannot move in that direction from the current tile? + */ + if ((DAT_ClimbLogicDefinedData::instance.BitFlagHelperForPathLinkage[direction] + & DAT_TileMapState::instance.PathLinkageLayer[tile]) + == 0) { + int _targetTile = DAT_TileMapState::instance.directionTranslationMatrix[y][direction] + tile; + if (ignoreAssassinClimbing == 0) { + if (DAT_UnitsState::instance.units[unitID].unitType == OpenSHC::Map::Units::UT_A_ASSASSIN) { + uVar3 = DAT_TileMapState::instance.LogicLayer[_targetTile]; + if ((uVar3 & 0x4a5014b1) == 0 + && (uVar4 = DAT_TileMapState::instance.LogicLayer[tile] & 0x100, + uVar4 == 0 || ((uVar3 & 0x100) == 0)) + && (uVar4 != 0 || ((uVar3 & 0x100) != 0))) { + ushort _height = DAT_TileMapState::instance.HeightLayer[tile]; + DAT_UnitsState::instance.units[unitID].animationCycleNumber = 0; + DAT_UnitsState::instance.units[unitID].field306_0x418 = 0; + if (uVar4 == 0) { + ushort _terrainHeight = DAT_TileMapState::instance.HeightLayer[_targetTile]; + byte bVar2 = DAT_TileMapState::instance.WallOwnerLayer[_targetTile]; + DAT_UnitsState::instance.units[unitID].state.generic + = OpenSHC::Map::Units::States::US_ASSASSIN_THROWING_HOOK; + DAT_UnitsState::instance.units[unitID].assassinHeightDifference + = _terrainHeight - _height; + DAT_UnitsState::instance.units[unitID] + .assassinClimbingUpUnk_OR_previousFacingDirection = 1; + DAT_UnitsState::instance.units[unitID].ownerOfAssassinScaledObject + = (bVar2 & 7) + 1; + } else { + ushort _terrainHeight2 = DAT_TileMapState::instance.HeightLayer[_targetTile]; + DAT_UnitsState::instance.units[unitID].state.generic + = OpenSHC::Map::Units::States::US_ASSASSIN_START_CLIMBING_DOWN; + DAT_UnitsState::instance.units[unitID].assassinHeightDifference + = _height - _terrainHeight2; + DAT_UnitsState::instance.units[unitID] + .assassinClimbingUpUnk_OR_previousFacingDirection = 0; + } + if (DAT_UnitsState::instance.units[unitID].assassinHeightDifference < 0) { + DAT_UnitsState::instance.units[unitID].assassinHeightDifference = 0; + } + return TRUE; + } + return FALSE; + } + } else { + uVar3 = DAT_TileMapState::instance.LogicLayer[_targetTile]; + if ((uVar3 & 0x40000000) != 0) { + return TRUE; + } + if ((DAT_TileMapState::instance.LogicLayer[tile] & 0x40000000U) != 0 + && (uVar3 & 0x4a5014b1) == 0) { + return ~(uVar3 >> 8) & TRUE; + } + } + } else { + if ((DAT_EntityState::instance.fireCount == 0) + || (DAT_UnitsState::instance.units[unitID].field295_0x40a != 0)) { + DAT_UnitsState::instance.units[unitID].counter = 0; + return TRUE; + } + if (DAT_TileMapState::instance + .EntityLayer[DAT_TileMapState::instance.directionTranslationMatrix[y][direction] + tile] + == 0) { + return TRUE; + } + if (DAT_EntityState::instance + .entityArray[DAT_TileMapState::instance.EntityLayer + [DAT_TileMapState::instance.directionTranslationMatrix[y][direction] + tile]] + .entityType + != OpenSHC::Map::Entities::ET_FIRE) { + return TRUE; + } + if ((DAT_TileMapState::instance.EntityLayer[tile] != 0) + && (DAT_EntityState::instance.entityArray[DAT_TileMapState::instance.EntityLayer[tile]] + .entityType + == OpenSHC::Map::Entities::ET_FIRE)) { + return TRUE; + } + DAT_UnitsState::instance.units[unitID].counter = DAT_UnitsState::instance.units[unitID].counter + 1; + DAT_UnitsState::instance.units[unitID].field280_0x3f4 = 5; + DAT_UnitsState::instance.units[unitID].field295_0x40a = 1; + } + return FALSE; + } + if (param_5 == 1) { + if ((DAT_TileMapState::instance + .LogicLayer[DAT_TileMapState::instance.directionTranslationMatrix[y][direction] + tile] + & 0x30U) + != 0) { + return FALSE; + } + if ((DAT_TileMapState::instance + .LogicLayer[DAT_TileMapState::instance.directionTranslationMatrix[y][direction] + tile] + & 1U) + != 0) { + return FALSE; + } + } + return TRUE; + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/doPathfinding.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/doPathfinding.cpp new file mode 100644 index 0000000000..3aaed15365 --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/doPathfinding.cpp @@ -0,0 +1,131 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/Map/Navigation/DirectionAlgorithmState.func.hpp" +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +#include "OpenSHC/Globals/DAT_PathFindingState.hpp" +#include "OpenSHC/Globals/DAT_DirectionAlgorithmState.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x004A9B20 + dword PathFindingState::doPathfinding(int param_1, int param_2) + { + BOOLEnum BVar3; + ushort uVar1 = DAT_TileMapState::instance.PathConnectionLayer + [DAT_ViewportRenderState::instance.translationMatrix[this->destinationY].addXgetTile + + this->destinationX]; + if (DAT_TileMapState::instance.PathConnectionLayer + [DAT_ViewportRenderState::instance.translationMatrix[this->unitY].addXgetTile + this->unitX] + != uVar1 + && this->climbIsIllegal == 0 && this->allAssassinsUnk == 0) { + if (uVar1 == 0) { + return (dword)(0); + } + dword dVar2 = MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::PathFindingState_Func::findConnectingAreaBetweenTwoAreas, DAT_PathFindingState::ptr)(param_1, + (dword)((int)((short)DAT_TileMapState::instance.PathConnectionLayer + [DAT_ViewportRenderState::instance.translationMatrix[this->unitY].addXgetTile + + this->unitX])), + (dword)((int)((short)uVar1))); + if (dVar2 == 0) { + return (dword)(0); + } + } + this->searchQueue.pathPlanIndex = 0; + this->field43_0x7c = 1; + if (this->climbIsIllegal == 0 && this->allAssassinsUnk == 0 + && (BVar3 = MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::PathFindingState_Func::tracePathPlanToDestinationViaUnoccupiedTiles, + this)(this->unitX, (uint)(this->unitY), (uint)(this->destinationX), (uint)(this->destinationY)), + BVar3 != FALSE)) { + this->DAT_Easy = this->DAT_Easy + 1; + return (dword)(this->searchQueue.pathPlanIndex); + } + this->DAT_Hard = this->DAT_Hard + 1; + this->field43_0x7c = 0; + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::DirectionAlgorithmState_Func::setAxisBasedDistanceResult, + DAT_DirectionAlgorithmState::ptr)(this->unitX, this->unitY, this->destinationX, this->destinationY); + int iVar4 = (DAT_DirectionAlgorithmState::instance.distanceHigh + 4) + * (DAT_DirectionAlgorithmState::instance.distanceHigh + 4) * 10; + this->searchQueue.pathPlanIndex = 0; + if (this->notAllAssassinsUnk != 0) { + BVar3 = MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::PathFindingState_Func::findLinkageBasedPathOrWalkRadius, this)( + this->unitX, (uint)(this->unitY), this->destinationX, this->destinationY, 100000, FALSE); + } else { + if (this->allAssassinsUnk == 0) { + BVar3 = MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::PathFindingState_Func::findSuitableSpawnLocationUnk, this)( + this->unitX, this->unitY, this->destinationX, this->destinationY, iVar4, 0); + } else { + BVar3 = MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::PathFindingState_Func::findLinkageBasedPathOrWalkRadius, this)( + this->unitX, (uint)(this->unitY), this->destinationX, this->destinationY, iVar4, FALSE); + } + if (BVar3 == FALSE) { + if (this->allAssassinsUnk != 0) { + BVar3 = MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::PathFindingState_Func::pathFindingWithBuildingsIncluded, this)( + this->unitX, (uint)(this->unitY), (uint)(this->destinationX), (uint)(this->destinationY), + 100000, 0); + } else if (this->climbIsIllegal != 0) { + BVar3 = MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::PathFindingState_Func::findPathUsingClimbingWithHeightMargin16, + this)(this->unitX, (uint)(this->unitY), (uint)(this->destinationX), + (uint)(this->destinationY), 100000, FALSE); + } else { + BVar3 = MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::PathFindingState_Func::findLinkageBasedPathOrWalkRadius, this)( + this->unitX, (uint)(this->unitY), this->destinationX, this->destinationY, 100000, FALSE); + } + } + } + if (BVar3 == FALSE) { + return (dword)(0); + } + if (this->allAssassinsUnk == 0) { + if (this->climbIsIllegal == 0) { + iVar4 = 1; + } else { + iVar4 = 2; + } + } else { + iVar4 = 3; + } + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::traceAndCommitPathPlan, this)( + this->unitX, (uint)(this->unitY), (uint)(this->destinationX), (uint)(this->destinationY), iVar4); + if ((param_2 == 0) && (this->field49_0x94 != 0)) { + this->searchQueue.pathPlanIndex = 0; + iVar4 = MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::PathFindingState_Func::calculatePathKeepAndWallsGatesNotAllowed, this)( + this->unitX, this->unitY, this->destinationX, this->destinationY, 100000); + if (iVar4 != 0) { + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::traceAndCommitPathPlan, this)( + this->unitX, (uint)(this->unitY), (uint)(this->destinationX), (uint)(this->destinationY), 1); + return (dword)(this->searchQueue.pathPlanIndex); + } + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::findLinkageBasedPathOrWalkRadius, + this)(this->unitX, (uint)(this->unitY), this->destinationX, this->destinationY, 100000, FALSE); + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::traceAndCommitPathPlan, this)( + this->unitX, (uint)(this->unitY), (uint)(this->destinationX), (uint)(this->destinationY), 1); + } + return (dword)(this->searchQueue.pathPlanIndex); + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/findAIZoneWithFlags.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/findAIZoneWithFlags.cpp new file mode 100644 index 0000000000..f11b8ae051 --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/findAIZoneWithFlags.cpp @@ -0,0 +1,112 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/IO/LowLevelMemory.func.hpp" +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +#include "OpenSHC/Globals/DAT_ClimbLogicDefinedData.hpp" +#include "OpenSHC/Globals/DAT_LowLevelMemory.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x0049EDF0 + BOOLEnum PathFindingState::findAIZoneWithFlags(int maxDistance, uint x, uint y, undefined4 aiInfoFlags) + { + int _candidate; + this->calculations = this->calculations + 1; + if (x > 399 || y > 399) { + return FALSE; + } + if (DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[y * 400 + x] == '\0') { + return FALSE; + } + this->searchGeneration = this->searchGeneration + 1; + if (32000 < this->searchGeneration) { + this->searchGeneration = 1; + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 0x27420, '\0', (void*)((int)(DAT_TileMapState::instance.WalkLayer))); + } + this->searchQueue.readIndex = 0; + this->searchQueue.writeIndex = 1; + this->searchQueue.currentDistance = 1; + this->searchQueue.yQueue[0] = (short)y; + this->searchQueue.xQueue[0] = (short)x; + int _startTile = DAT_ViewportRenderState::instance.translationMatrix[y].addXgetTile + x; + this->searchQueue.tilesQueue[0] = _startTile; + DAT_TileMapState::instance.CertainPathLayer[_startTile] = (short)this->searchQueue.currentDistance; + DAT_TileMapState::instance.WalkLayer[this->searchQueue.tilesQueue[0]] = (short)this->searchGeneration; + if (this->searchQueue.readIndex != this->searchQueue.writeIndex) { + while (true) { + int _tile = this->searchQueue.tilesQueue[this->searchQueue.readIndex]; + if (_tile < 0) { + break; + } + if (0x13a10 <= _tile) { + break; + } + int sVar1 = (int)this->searchQueue.xQueue[this->searchQueue.readIndex]; + int sVar2 = (int)this->searchQueue.yQueue[this->searchQueue.readIndex]; + this->searchQueue.currentDistance = (int)DAT_TileMapState::instance.CertainPathLayer[_tile]; + if (0x13a10 < (int)this->searchQueue.currentDistance) { + return FALSE; + } + if ((int)this->searchQueue.currentDistance > maxDistance) { + return FALSE; + } + for (int _direction = 0; _direction < 8; _direction = _direction + 1) { + if ((DAT_TileMapState::instance.PathLinkageLayer[_tile] + & DAT_ClimbLogicDefinedData::instance.BitFlagHelperForPathLinkage[_direction]) + != 0 + && (_candidate + = DAT_TileMapState::instance.directionTranslationMatrix[sVar2][_direction] + _tile, + DAT_TileMapState::instance.WalkLayer[_candidate] != this->searchGeneration)) { + if ((DAT_TileMapState::instance.AIInfoLayer[_candidate] & (byte)aiInfoFlags) != 0) { + this->ALG_ResultY = (int)sVar2; + this->ALG_ResultX = (int)sVar1; + return TRUE; + } + DAT_TileMapState::instance.CertainPathLayer[_candidate] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[_candidate] = (short)this->searchGeneration; + this->searchQueue.xQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction] + .short_.xOffset + + sVar1; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction] + .short_.yOffset + + sVar2; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = _candidate; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + } + this->searchQueue.readIndex = this->searchQueue.readIndex + 1; + if (0x13a10 <= (int)this->searchQueue.readIndex) { + this->searchQueue.readIndex = 0; + } + if (this->searchQueue.readIndex == this->searchQueue.writeIndex) { + return FALSE; + } + } + } + return FALSE; + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/findAccessibleWallAndNearbyFreeTile.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/findAccessibleWallAndNearbyFreeTile.cpp new file mode 100644 index 0000000000..26aba64015 --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/findAccessibleWallAndNearbyFreeTile.cpp @@ -0,0 +1,188 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/IO/LowLevelMemory.func.hpp" +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +#include "OpenSHC/Globals/DAT_LowLevelMemory.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_UnitsState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x004A3220 + BOOLEnum PathFindingState::findAccessibleWallAndNearbyFreeTile( + uint unitID, int tile, int* pFreeTile, int* pDefensesTile) + { + uint uVar2; + int _candidateNorthOrSouth; + this->searchGeneration = this->searchGeneration + 1; + this->calculations = this->calculations + 1; + if (32000 < this->searchGeneration) { + this->searchGeneration = 1; + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 0x27420, '\0', (void*)((int)(DAT_TileMapState::instance.WalkLayer))); + } + int _startY = (short)DAT_ViewportRenderState::instance.tileTranslationMatrix_YComponent[tile]; + this->searchQueue.yQueue[0] = (short)_startY; + this->searchQueue.xQueue[0] + = (short)tile - (short)DAT_ViewportRenderState::instance.translationMatrix[_startY].addXgetTile; + this->searchQueue.tilesQueue[0] = tile; + this->searchQueue.readIndex = 0; + this->searchQueue.writeIndex = 1; + this->searchQueue.currentDistance = 1; + DAT_TileMapState::instance.CertainPathLayer[tile] = 1; + DAT_TileMapState::instance.WalkLayer[this->searchQueue.tilesQueue[0]] = (short)this->searchGeneration; + if (this->searchQueue.readIndex != this->searchQueue.writeIndex) { + while (true) { + uint _tile = this->searchQueue.tilesQueue[this->searchQueue.readIndex]; + if ((int)_tile < 0) { + break; + } + if (0x13a10 <= (int)_tile) { + break; + } + int sVar1 = (int)this->searchQueue.xQueue[this->searchQueue.readIndex]; + int _y = (int)this->searchQueue.yQueue[this->searchQueue.readIndex]; + this->searchQueue.currentDistance = (int)DAT_TileMapState::instance.CertainPathLayer[_tile]; + if (0x13a10 < (int)this->searchQueue.currentDistance) { + return FALSE; + } + if (0xc < (int)this->searchQueue.currentDistance) { + return FALSE; + } + if (3 < (int)this->searchQueue.currentDistance + && (DAT_TileMapState::instance.LogicLayer[_tile] & 0x100U) != 0) { + /* + wall or gatehouse (or tower?) + */ + uVar2 = MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::findFreeTileNearby, + DAT_UnitsState::ptr)(unitID, _tile); + *pFreeTile = uVar2; + if (uVar2 != 0) { + *pDefensesTile = _tile; + return TRUE; + } + } + /* + every other unit searches in a different direction + */ + uVar2 = (unitID & 1) * 4 + 1; + int local_8 = 2; + do { + uint _direction = uVar2 - 1 & 7; + _candidateNorthOrSouth + = DAT_TileMapState::instance.directionTranslationMatrix[_y][_direction] + _tile; + if (DAT_TileMapState::instance.WalkLayer[_candidateNorthOrSouth] != this->searchGeneration + && (DAT_TileMapState::instance.LogicLayer[_candidateNorthOrSouth] & 0x30) == 0) { + DAT_TileMapState::instance.CertainPathLayer[_candidateNorthOrSouth] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[_candidateNorthOrSouth] + = (short)this->searchGeneration; + this->searchQueue.xQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction] + .short_.xOffset + + sVar1; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction] + .short_.yOffset + + _y; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = _candidateNorthOrSouth; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + uint uVar4 = uVar2 & 7; + int iVar3 = DAT_TileMapState::instance.directionTranslationMatrix[_y][uVar4] + _tile; + if (DAT_TileMapState::instance.WalkLayer[iVar3] != this->searchGeneration + && (DAT_TileMapState::instance.LogicLayer[iVar3] & 0x30) == 0) { + DAT_TileMapState::instance.CertainPathLayer[iVar3] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[iVar3] = (short)this->searchGeneration; + this->searchQueue.xQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[uVar4] + .short_.xOffset + + sVar1; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[uVar4] + .short_.yOffset + + _y; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = iVar3; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + uVar4 = uVar2 + 1 & 7; + iVar3 = DAT_TileMapState::instance.directionTranslationMatrix[_y][uVar4] + _tile; + if (DAT_TileMapState::instance.WalkLayer[iVar3] != this->searchGeneration + && (DAT_TileMapState::instance.LogicLayer[iVar3] & 0x30) == 0) { + DAT_TileMapState::instance.CertainPathLayer[iVar3] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[iVar3] = (short)this->searchGeneration; + this->searchQueue.xQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[uVar4] + .short_.xOffset + + sVar1; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[uVar4] + .short_.yOffset + + _y; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = iVar3; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + uVar4 = uVar2 + 2 & 7; + iVar3 = DAT_TileMapState::instance.directionTranslationMatrix[_y][uVar4] + _tile; + if (DAT_TileMapState::instance.WalkLayer[iVar3] != this->searchGeneration + && (DAT_TileMapState::instance.LogicLayer[iVar3] & 0x30) == 0) { + DAT_TileMapState::instance.CertainPathLayer[iVar3] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[iVar3] = (short)this->searchGeneration; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[uVar4] + .short_.yOffset + + _y; + this->searchQueue.xQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[uVar4] + .short_.xOffset + + sVar1; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = iVar3; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + uVar2 = uVar2 + 4; + local_8 = local_8 + -1; + } while (local_8 != 0); + this->searchQueue.readIndex = this->searchQueue.readIndex + 1; + if (0x13a10 <= (int)this->searchQueue.readIndex) { + this->searchQueue.readIndex = 0; + } + if (this->searchQueue.readIndex == this->searchQueue.writeIndex) { + return FALSE; + } + } + } + return FALSE; + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/findAppropriateLocationForSiegeTent.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/findAppropriateLocationForSiegeTent.cpp new file mode 100644 index 0000000000..9e0972c8f0 --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/findAppropriateLocationForSiegeTent.cpp @@ -0,0 +1,347 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/IO/LowLevelMemory.func.hpp" + +#include "OpenSHC/Globals/DAT_ClimbLogicDefinedData.hpp" +#include "OpenSHC/Globals/DAT_LowLevelMemory.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_TroopValueState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + * Finds an appropriate location for placing a siege tent near a target position. * Uses breadth-first search + * (BFS) to explore tiles radiating outward from the starting position. * * @param this - + * PathFindingState object pointer * @param distance? - Maximum search distance (typically 100 or 200 tiles) + * * @param x - Starting X coordinate (0-399) * @param y - Starting Y coordinate (0-399) * @param + * selectionID - ID for selected unit/object (unused in function body) * @param requiredDistanceFromAIZone - + * Exact match required for AI zone tactical distance if nonzero * @param playerID - Current player's ID + * * @return Tile index of valid siege tent location, or 0 if none found decompilerscript: committed: + * 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x0049F7D0 + dword PathFindingState::findAppropriateLocationForSiegeTent( + int distanceUnk, uint x, uint y, undefined4 selectionID, uint requiredDistanceFromAIZone, int playerID) + { + int* piVar4; + int iVar5; + int iVar6; + dword _offsetTile; + uint uVar7; + uint _minHeight; + int local_c; + int _tile; + /* + === INITIAL VALIDATION === Check if coordinates are within map bounds (400x400) and if the tile is + walkable + */ + if (399 < x || 399 < y) { + /* + Invalid position - out of bounds or unwalkable + */ + return (dword)(0); + } + if (DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[y * 400 + x] == '\0') { + /* + Invalid position - out of bounds or unwalkable + */ + return (dword)(0); + } + /* + === PATHFINDING STATE INITIALIZATION === Increment calculation counter (for profiling/debugging) + */ + this->calculations = this->calculations + 1; + /* + Increment the "active flag" value used to mark visited tiles this search iteration + */ + this->searchGeneration = this->searchGeneration + 1; + /* + If flag value exceeds 32000, reset to 1 and clear the entire WalkLayer This prevents overflow and avoids + having to clear the layer every search + */ + if (32000 < this->searchGeneration) { + this->searchGeneration = 1; + /* + Clear 160800 bytes 80400 short values + */ + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 160800, '\0', (void*)((int)(DAT_TileMapState::instance.WalkLayer))); + } + /* + === BFS QUEUE INITIALIZATION === Initialize BFS queue indices Current tile being processed + */ + this->searchQueue.readIndex = 0; + /* + Next free slot in queue + */ + this->searchQueue.writeIndex = 1; + /* + Starting distance + */ + this->searchQueue.currentDistance = 1; + /* + Convert 2D coordinates to 1D tile index + */ + this->searchQueue.yQueue[0] = (short)y; + /* + Add starting position to queue + */ + this->searchQueue.tilesQueue[0] = DAT_ViewportRenderState::instance.translationMatrix[y].addXgetTile + x; + /* + Mark starting tile with distance 1 + */ + DAT_TileMapState::instance.CertainPathLayer[this->searchQueue.tilesQueue[0]] = 1; + /* + Mark as visited with current active flag value + */ + DAT_TileMapState::instance.WalkLayer[this->searchQueue.tilesQueue[0]] = (short)this->searchGeneration; + /* + === MAIN BFS LOOP === Continue while there are tiles in the queue to process + */ + if (this->searchQueue.readIndex != this->searchQueue.writeIndex) { + while (true) { + _tile = this->searchQueue.tilesQueue[this->searchQueue.readIndex]; + if (_tile < 0 || 0x13a10 <= _tile) { + break; + } + /* + Get Y coordinate of current tile being processed + */ + int sVar1 = this->searchQueue.yQueue[this->searchQueue.readIndex]; + /* + Get distance from start for current tile + */ + this->searchQueue.currentDistance = (int)DAT_TileMapState::instance.CertainPathLayer[_tile]; + /* + Safety check: if distance exceeds max tile count, abort + */ + if (80400 < (int)this->searchQueue.currentDistance) { + return (dword)(0); + } + /* + If we've exceeded search radius, stop searching + */ + if ((int)this->searchQueue.currentDistance > distanceUnk) { + return (dword)(0); + } + /* + === EXPLORE 8 ADJACENT TILES === Check all 8 cardinal/diagonal directions from current tile + */ + y = 0; + do { + /* + Check if movement is possible in this direction (using bitflag for direction y) Check if + adjacent tile hasn't been visited this iteration + */ + if ((DAT_TileMapState::instance.PathLinkageLayer[_tile] + & DAT_ClimbLogicDefinedData::instance.BitFlagHelperForPathLinkage[y]) + != 0 + && (_offsetTile = DAT_TileMapState::instance.directionTranslationMatrix[sVar1][y] + _tile, + DAT_TileMapState::instance.WalkLayer[_offsetTile] != this->searchGeneration)) { + int bVar2 = 1; + /* + === AI Zone DISTANCE CHECK === If specified (i.e. not 0), then the strategic distance of + the current tile must be exactly that value + */ + if (requiredDistanceFromAIZone != 0) { + bVar2 = true; + if (DAT_TileMapState::instance.SEC_PathfindingCostTileMap1105[*( + int*)((int)DAT_TroopValueState::instance.attackInfo.hackValuesArray + + playerID * 0x177bc + -0x10)][_offsetTile] + != requiredDistanceFromAIZone) { + bVar2 = 0; + } + } + /* + === SIEGE TENT PLACEMENT VALIDATION === Only check for valid placement if distance > 4 + (minimum spacing requirement) + */ + if (4 < (int)this->searchQueue.currentDistance + && (short)DAT_TileMapState::instance.UnitLayer[_offsetTile] == 0 && bVar2) { + iVar6 = 0; + /* + Get height of candidate tile + */ + uVar7 = (uint)DAT_TileMapState::instance.HeightLayer[_offsetTile]; + local_c = 0; + /* + Get pointer to movement direction offsets for checking surrounding tiles Track + minimum height in surrounding area + */ + _minHeight = uVar7; + /* + === CHECK 8 SURROUNDING TILES FOR TENT PLACEMENT === Loop checks tiles in groups of + 4 for optimization + */ + do { + /* + Check first tile in group + */ + iVar5 = DAT_TileMapState::instance + .directionTranslationMatrix[DAT_TerrainDefinedData::instance + .clockwiseCardinalTranslationMatrix[y] + .int_.yOffset + + (int)sVar1][local_c] + + _offsetTile; + /* + Disqualify if tile has: impassable terrain, units, or buildings 0x4a7014b1 + checks for: sea, border, border_edge, rocky, building, tree, river, ford, + crenel wall impassible, farm field hop tree, farm field dairy fence, moat, farm + */ + if ((DAT_TileMapState::instance.LogicLayer[iVar5] & 0x4a7014b1U) != 0 + || (DAT_TileMapState::instance.LogicLayer[iVar5] & 4U) != 0 + || (short)DAT_TileMapState::instance.UnitLayer[iVar5] != 0 + || DAT_TileMapState::instance.BuildingLayer[iVar5] != 0) + break; + /* + Track height variation (for flatness check) + */ + uint uVar3 = (uint)DAT_TileMapState::instance.HeightLayer[iVar5]; + if ((int)uVar3 > (int)uVar7) { + uVar7 = uVar3; + } else if ((int)uVar3 < (int)_minHeight) { + _minHeight = uVar3; + } + /* + Update maximum height Repeat checks for tiles 2, 3, and 4 in the group (Pattern + repeats with piVar4[0], + DAT_TileMapState::instance.directionTranslationMatrix[DAT_TerrainDefinedData::instance + .clockwiseCardinalTranslationMatrix[y] .int_.yOffset + (int)sVar1][local_c + 2], + DAT_TileMapState::instance.directionTranslationMatrix[DAT_TerrainDefinedData::instance + .clockwiseCardinalTranslationMatrix[y] .int_.yOffset + (int)sVar1][local_c + 3]) + Each tile checks: LogicLayer, UnitLayer, BuildingLayer, HeightLayer + */ + iVar5 = DAT_TileMapState::instance + .directionTranslationMatrix[DAT_TerrainDefinedData::instance + .clockwiseCardinalTranslationMatrix[y] + .int_.yOffset + + (int)sVar1][local_c + 1] + + _offsetTile; + if ((DAT_TileMapState::instance.LogicLayer[iVar5] & 0x4a7014b1U) != 0 + || (DAT_TileMapState::instance.LogicLayer[iVar5] & 4U) != 0 + || (short)DAT_TileMapState::instance.UnitLayer[iVar5] != 0 + || DAT_TileMapState::instance.BuildingLayer[iVar5] != 0) { + iVar6 = iVar6 + 1; + break; + } + uVar3 = (uint)DAT_TileMapState::instance.HeightLayer[iVar5]; + if ((int)uVar3 > (int)uVar7) { + uVar7 = uVar3; + } else if ((int)uVar3 < (int)_minHeight) { + _minHeight = uVar3; + } + iVar5 = DAT_TileMapState::instance + .directionTranslationMatrix[DAT_TerrainDefinedData::instance + .clockwiseCardinalTranslationMatrix[y] + .int_.yOffset + + (int)sVar1][local_c + 2] + + _offsetTile; + if ((DAT_TileMapState::instance.LogicLayer[iVar5] & 0x4a7014b1U) != 0 + || (DAT_TileMapState::instance.LogicLayer[iVar5] & 4U) != 0 + || (short)DAT_TileMapState::instance.UnitLayer[iVar5] != 0 + || DAT_TileMapState::instance.BuildingLayer[iVar5] != 0) { + iVar6 = iVar6 + 2; + break; + } + uVar3 = (uint)DAT_TileMapState::instance.HeightLayer[iVar5]; + if ((int)uVar3 > (int)uVar7) { + uVar7 = uVar3; + } else if ((int)uVar3 < (int)_minHeight) { + _minHeight = uVar3; + } + iVar5 = DAT_TileMapState::instance + .directionTranslationMatrix[DAT_TerrainDefinedData::instance + .clockwiseCardinalTranslationMatrix[y] + .int_.yOffset + + (int)sVar1][local_c + 3] + + _offsetTile; + if ((DAT_TileMapState::instance.LogicLayer[iVar5] & 0x4a7014b1U) != 0 + || (DAT_TileMapState::instance.LogicLayer[iVar5] & 4U) != 0 + || (short)DAT_TileMapState::instance.UnitLayer[iVar5] != 0 + || DAT_TileMapState::instance.BuildingLayer[iVar5] != 0) { + iVar6 = iVar6 + 3; + break; + } + uVar3 = (uint)DAT_TileMapState::instance.HeightLayer[iVar5]; + if ((int)uVar3 > (int)uVar7) { + uVar7 = uVar3; + } else if ((int)uVar3 < (int)_minHeight) { + _minHeight = uVar3; + } + local_c = local_c + 4; + iVar6 = iVar6 + 4; + } while (local_c < 8); + /* + === FINAL VALIDATION === If all 8 surrounding tiles are clear (iVar6 == 8) AND + terrain is relatively flat (height difference < 12) + */ + if (iVar6 == 8 && (int)(uVar7 - _minHeight) < 0xc) { + /* + FOUND VALID LOCATION! + */ + return (dword)(_offsetTile); + } + } + /* + === ADD TILE TO BFS QUEUE === Mark this tile's distance (current distance + 1) + */ + DAT_TileMapState::instance.CertainPathLayer[_offsetTile] + = (short)this->searchQueue.currentDistance + 1; + /* + Mark as visited + */ + DAT_TileMapState::instance.WalkLayer[_offsetTile] = (short)this->searchGeneration; + /* + Add Y coordinate to queue + */ + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[y].short_.yOffset + + sVar1; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = _offsetTile; + /* + Increment queue write position + */ + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (80400 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + /* + Move to next direction + */ + y = y + 1; + /* + Process all 8 directions + */ + } while ((int)y < 8); + /* + === ADVANCE TO NEXT TILE IN QUEUE === + */ + this->searchQueue.readIndex = this->searchQueue.readIndex + 1; + if (80400 <= (int)this->searchQueue.readIndex) { + this->searchQueue.readIndex = 0; + } + /* + Check if queue is empty (read position caught up to write position) + */ + if (this->searchQueue.readIndex == this->searchQueue.writeIndex) { + return (dword)(0); + } + } + } + /* + No valid location found + */ + return (dword)(0); + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/findArcherRelatedAttackInfoIndex.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/findArcherRelatedAttackInfoIndex.cpp new file mode 100644 index 0000000000..038cc361dc --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/findArcherRelatedAttackInfoIndex.cpp @@ -0,0 +1,125 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/IO/LowLevelMemory.func.hpp" +#include "OpenSHC/Map/Units/TroopValueState.func.hpp" + +#include "OpenSHC/Globals/DAT_ClimbLogicDefinedData.hpp" +#include "OpenSHC/Globals/DAT_LowLevelMemory.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_TribesState.hpp" +#include "OpenSHC/Globals/DAT_TroopValueState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + + /* + WARNING: Type propagation algorithm not settling + */ + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x0049F040 + int PathFindingState::findArcherRelatedAttackInfoIndex(int max, uint x, uint y, int tribeID) + { + int iVar4; + int _candidate; + if (399 < x || 399 < y) { + return 0; + } + if (DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[y * 400 + x] == '\0') { + return 0; + } + this->calculations = this->calculations + 1; + this->searchGeneration = this->searchGeneration + 1; + if (32000 < this->searchGeneration) { + this->searchGeneration = 1; + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 0x27420, '\0', (void*)((int)(DAT_TileMapState::instance.WalkLayer))); + } + this->searchQueue.readIndex = 0; + this->searchQueue.writeIndex = 1; + this->searchQueue.currentDistance = 1; + this->searchQueue.yQueue[0] = (short)y; + this->searchQueue.xQueue[0] = (short)x; + int _startTile = DAT_ViewportRenderState::instance.translationMatrix[y].addXgetTile + x; + this->searchQueue.tilesQueue[0] = _startTile; + DAT_TileMapState::instance.CertainPathLayer[_startTile] = 1; + DAT_TileMapState::instance.WalkLayer[this->searchQueue.tilesQueue[0]] = (short)this->searchGeneration; + if (this->searchQueue.readIndex != this->searchQueue.writeIndex) { + while (true) { + int _tile = this->searchQueue.tilesQueue[this->searchQueue.readIndex]; + if (_tile < 0) { + break; + } + if (0x13a10 <= _tile) { + break; + } + int sVar1 = (int)this->searchQueue.xQueue[this->searchQueue.readIndex]; + int sVar2 = (int)this->searchQueue.yQueue[this->searchQueue.readIndex]; + this->searchQueue.currentDistance = (int)DAT_TileMapState::instance.CertainPathLayer[_tile]; + if (0x13a10 < (int)this->searchQueue.currentDistance) { + return 0; + } + if ((int)this->searchQueue.currentDistance > max) { + return 0; + } + for (int iVar5 = 0; iVar5 < 8; iVar5 = iVar5 + 1) { + if ((DAT_TileMapState::instance.PathLinkageLayer[_tile] + & DAT_ClimbLogicDefinedData::instance.BitFlagHelperForPathLinkage[iVar5]) + != 0 + && (_candidate + = DAT_TileMapState::instance.directionTranslationMatrix[sVar2][iVar5] + _tile, + DAT_TileMapState::instance.WalkLayer[_candidate] != this->searchGeneration)) { + if (4 < (int)this->searchQueue.currentDistance + && (DAT_TileMapState::instance.AIInfoLayer[_candidate] & 0x10) != 0 + && (iVar4 = MACRO_CALL_MEMBER( + OpenSHC::Map::Units::TroopValueState_Func::findOrReserveArcherPointSlot, + DAT_TroopValueState::ptr)(_candidate), + iVar4 != 0) + && iVar4 != DAT_TribesState::instance.tribes[tribeID].archerRelated + && iVar4 != DAT_TribesState::instance.tribes[tribeID].archerRelated2 + && DAT_TroopValueState::instance.attackInfo.arch2ValuesArray[iVar4 * 2 + 0x3eb].tile + == 0 + && DAT_TroopValueState::instance.attackInfo.arch2ValuesArray[iVar4 * 2 + 0x3ea] + .buildingID + == 0) { + return iVar4; + } + DAT_TileMapState::instance.CertainPathLayer[_candidate] + = (short)this->searchQueue.currentDistance + 1; + int sVar3 = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[iVar5] + .short_.xOffset; + DAT_TileMapState::instance.WalkLayer[_candidate] = (short)this->searchGeneration; + this->searchQueue.xQueue[this->searchQueue.writeIndex] = sVar3 + sVar1; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[iVar5] + .short_.yOffset + + sVar2; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = _candidate; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + } + this->searchQueue.readIndex = this->searchQueue.readIndex + 1; + if (0x13a10 <= (int)this->searchQueue.readIndex) { + this->searchQueue.readIndex = 0; + } + if (this->searchQueue.readIndex == this->searchQueue.writeIndex) { + return 0; + } + } + } + return 0; + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/findBestAdjacentClimbTileToTarget.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/findBestAdjacentClimbTileToTarget.cpp new file mode 100644 index 0000000000..1e4c3fef0c --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/findBestAdjacentClimbTileToTarget.cpp @@ -0,0 +1,103 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/Map/Buildings/BuildingsState.func.hpp" +#include "OpenSHC/Map/Navigation/DirectionAlgorithmState.func.hpp" +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" +#include "OpenSHC/Map/Location/Point8IntXY.hpp" + +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_DirectionAlgorithmState.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + using OpenSHC::Map::Location::Point8IntXY; + + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + Checks all cardinal neighbours of target tile (param_4, param_5) for tiles that are height-compatible + (within param_5 height margin) and navigable from (param_2, param_3) via + calculateCanPlayerUnitsNavigateToAreaFromArea. Uses calcApproxEuclideanDistance to pick the closest valid + neighbour. Stores the result in PathFindingState.climbX/climbY. Returns 1 if a suitable tile was found, 0 + otherwise. renamed by: Claude Sonnet 4.6 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x004A5DA0 + undefined4 PathFindingState::findBestAdjacentClimbTileToTarget( + int param_1, uint param_2, uint param_3, uint param_4, uint param_5) + { + ushort uVar1; + int iVar2; + int (*paiVar3)[8]; + uint uVar4; + int iVar5; + int iVar6; + int* piVar7; + uint local_18; + int local_10; + undefined4 local_8; + if (399 < param_2 || 399 < param_3) { + return (undefined4)(0); + } + if (DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[param_3 * 400 + param_2] == '\0') { + return (undefined4)(0); + } + if (param_4 <= 399 && param_5 <= 399 + && DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[param_5 * 400 + param_4] != '\0') { + iVar5 = DAT_ViewportRenderState::instance.translationMatrix[param_5].addXgetTile + param_4; + local_18 = (uint)DAT_TileMapState::instance.HeightLayer[iVar5]; + uVar1 + = DAT_TileMapState::instance + .PathConnectionLayer[DAT_ViewportRenderState::instance.translationMatrix[param_3].addXgetTile + + param_2]; + local_8 = 0; + local_10 = 1000; + if (DAT_TileMapState::instance.BuildingLayer[iVar5] != 0) { + iVar2 = MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::getBuildingHeightForBuildingID, + DAT_BuildingsState::ptr)((int)DAT_TileMapState::instance.BuildingLayer[iVar5]); + local_18 = local_18 + iVar2; + } + piVar7 = &DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[0].int_.yOffset; + paiVar3 = DAT_TileMapState::instance.directionTranslationMatrix + param_5; + do { + iVar6 = (*paiVar3)[0] + iVar5; + iVar2 = MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::PathFindingState_Func::calculateCanPlayerUnitsNavigateToAreaFromArea, + this)(param_1, (dword)((int)((short)uVar1)), + (dword)((int)((short)DAT_TileMapState::instance.PathConnectionLayer[iVar6])), 0); + if (iVar2 != 0) { + uVar4 = (uint)DAT_TileMapState::instance.HeightLayer[iVar6]; + if (DAT_TileMapState::instance.BuildingLayer[iVar6] != 0) { + iVar2 = MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::getBuildingHeightForBuildingID, + DAT_BuildingsState::ptr)((int)DAT_TileMapState::instance.BuildingLayer[iVar6]); + uVar4 = uVar4 + iVar2; + } + if ((int)local_18 <= (int)(uVar4 + 0x10) && (int)local_18 >= (int)(uVar4 - 0x10) + && (MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::DirectionAlgorithmState_Func::setAxisBasedDistanceResult, + DAT_DirectionAlgorithmState::ptr)(param_2, (int)(param_3), + (int)(((Point8IntXY*)(piVar7 + -1))->xOffset + param_4), (int)(*piVar7 + param_5)), + DAT_DirectionAlgorithmState::instance.distanceHigh < local_10)) { + local_10 = DAT_DirectionAlgorithmState::instance.distanceHigh; + this->climbX = ((Point8IntXY*)(piVar7 + -1))->xOffset + param_4; + this->climbY = *piVar7 + param_5; + local_8 = 1; + } + } + paiVar3 = (int (*)[8])(*paiVar3 + 1); + piVar7 = piVar7 + 2; + } while ((int)piVar7 < (int)&DAT_TerrainDefinedData::instance.field61_0x138); + return (undefined4)(local_8); + } + return (undefined4)(0); + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/findBestAttackTargetTileWithHeightAndOwner.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/findBestAttackTargetTileWithHeightAndOwner.cpp new file mode 100644 index 0000000000..5928705101 --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/findBestAttackTargetTileWithHeightAndOwner.cpp @@ -0,0 +1,227 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/IO/LowLevelMemory.func.hpp" +#include "OpenSHC/Map/Buildings/BuildingsState.func.hpp" +#include "OpenSHC/Map/Navigation.func.hpp" +#include "OpenSHC/Game/GameMode.hpp" + +#include "OpenSHC/Globals/DAT_BuildingDefinedData.hpp" +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_ClimbLogicDefinedData.hpp" +#include "OpenSHC/Globals/DAT_GameSynchronyState.hpp" +#include "OpenSHC/Globals/DAT_LowLevelMemory.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + + using OpenSHC::Game::GameMode; + + /* + WARNING: Enum "DPSEND_EnumInt": Some values do not have unique names + */ + /* + WARNING: Enum "DPERRInt": Some values do not have unique names + */ + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + BFS from (param_2, param_3) up to distance param_1, scoring enemy buildings and walls owned by player + param_7. Buildings score higher for defensive structures (0x400 flag), distance, and fire state. Walls are + scored by height difference from base terrain. The best-scoring tile coordinates are written to ALG_TargetX, + ALG_TargetY, and ALG_TargetTile. Height traversal cost is weighted in 3 tiers based on param_5. renamed + by: Claude Sonnet 4.6 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x004A6010 + void PathFindingState::findBestAttackTargetTileWithHeightAndOwner(int param_1, uint param_2, uint param_3, + int param_4, int param_5, int param_6, int param_7, int param_8, int param_9) + { + short sVar5; + int iVar7; + int iVar9; + int (*paiVar12)[3]; + int local_20; + int local_14; + int local_10; + uint local_c; + uint local_8; + local_14 = -1; + local_10 = -1; + local_c = -1; + this->calculations = this->calculations + 1; + local_20 = 1000000; + this->ALG_TargetTile = 0; + this->ALG_TargetY = 0; + this->ALG_TargetX = 0; + if (param_2 > 399 || param_3 > 399) { + return; + } + if (DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[param_3 * 400 + param_2] == '\0') { + return; + } + this->searchGeneration = this->searchGeneration + 1; + if (32000 < this->searchGeneration) { + this->searchGeneration = 1; + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 0x27420, '\0', (void*)((int)(DAT_TileMapState::instance.WalkLayer))); + } + this->searchQueue.currentDistance = 1; + this->searchQueue.writeIndex = 1; + this->searchQueue.readIndex = 0; + this->searchQueue.yQueue[0] = (short)param_3; + this->searchQueue.xQueue[0] = (short)param_2; + int iVar6 = DAT_ViewportRenderState::instance.translationMatrix[param_3].addXgetTile + param_2; + this->searchQueue.tilesQueue[0] = iVar6; + DAT_TileMapState::instance.CertainPathLayer[iVar6] = (short)this->searchQueue.currentDistance; + DAT_TileMapState::instance.WalkLayer[this->searchQueue.tilesQueue[0]] = (short)this->searchGeneration; + uint uVar10 = (uint)DAT_TileMapState::instance.HeightLayer[iVar6]; + if (this->searchQueue.readIndex != this->searchQueue.writeIndex) { + do { + uint uVar4 = this->searchQueue.tilesQueue[this->searchQueue.readIndex]; + if (0x13a10 <= uVar4) + break; + int sVar1 = (int)this->searchQueue.xQueue[this->searchQueue.readIndex]; + int sVar2 = (int)this->searchQueue.yQueue[this->searchQueue.readIndex]; + iVar6 = (int)sVar2; + uint uVar8 = DAT_TileMapState::instance.LogicLayer[uVar4]; + uint uVar11 = (uint)DAT_TileMapState::instance.SEC_PathfindingCostTileMap1105[param_7][uVar4]; + this->searchQueue.currentDistance = (int)DAT_TileMapState::instance.CertainPathLayer[uVar4]; + if ((int)this->searchQueue.currentDistance <= param_1) { + if ((DAT_GameSynchronyState::instance.currentGameMode == OpenSHC::Game::GM_SOLITARY) + && (7 < param_6)) { + uVar11 = 1; + } + if ((uVar8 & 2) == 0) { + if ((uVar8 & 0x10100) == 0 || uVar11 == 0 || param_8 <= (int)uVar11) { + if ((uVar8 & 0x10000400) != 0 && uVar11 != 0 && (int)uVar11 < param_8 + && (iVar9 = (int)DAT_TileMapState::instance.BuildingLayer[uVar4], + iVar9 != 0 + && (DAT_BuildingDefinedData::instance.BuildingTypeHasHealth + [(short)DAT_BuildingsState::instance.buildings[iVar9].buildingType] + != 0)) + && DAT_BuildingsState::instance.buildings[iVar9].owner == param_7 + && (param_9 == 0 + || ((iVar7 = MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func:: + getBuildingFlammabilityFactor, + DAT_BuildingsState::ptr)(iVar9), + iVar7 != 0 + && (DAT_BuildingsState::instance.buildings[iVar9].fireDuration + == 0))))) { + iVar9 = 0x96; + if ((uVar8 & 0x400) == 0) { + iVar9 = 0x4b; + } + if ((int)this->searchQueue.currentDistance <= 0) { + iVar9 = 100000; + } else if ((int)this->searchQueue.currentDistance < 0x10) { + iVar9 = (iVar9 + -100) * this->searchQueue.currentDistance + 0x5dc; + } else { + iVar9 = this->searchQueue.currentDistance * iVar9; + } + if (iVar9 < local_20 + && (iVar7 + = MACRO_CALL(OpenSHC::Map::Navigation_Func::CalcApproxEuclideanDistance)( + param_2, (int)(sVar1), (int)(param_3), iVar6), + iVar7 <= param_1)) { + local_20 = iVar9; + local_14 = (int)sVar1; + local_10 = iVar6; + local_c = uVar4; + } + } + } else if ((DAT_TileMapState::instance.WallOwnerLayer[uVar4] & 7) + 1 == param_7 + && param_9 == 0) { + iVar9 = (uint)DAT_TileMapState::instance.HeightLayer[uVar4] + - (uint)DAT_TileMapState::instance.DefaultHeightLayer[uVar4]; + if ((int)this->searchQueue.currentDistance <= 0) { + iVar9 = 100000; + } else if ((int)this->searchQueue.currentDistance < 0x10) { + iVar9 = (0x14 - this->searchQueue.currentDistance) * 300 + iVar9; + } else { + iVar9 = this->searchQueue.currentDistance * 100 + iVar9; + } + if (iVar9 < local_20 + && (iVar7 = MACRO_CALL(OpenSHC::Map::Navigation_Func::CalcApproxEuclideanDistance)( + param_2, (int)(sVar1), (int)(param_3), iVar6), + iVar7 <= param_1)) { + local_20 = iVar9; + local_14 = (int)sVar1; + local_10 = iVar6; + local_c = uVar4; + } + } + } + local_8 = ((int)(char)this->searchQueue.currentDistance & 1U) * 2 | 1; + paiVar12 = DAT_ClimbLogicDefinedData::instance.field13_0x13c + param_4; + do { + iVar9 = (*paiVar12)[0]; + iVar7 = DAT_TileMapState::instance.directionTranslationMatrix[iVar6][iVar9] + uVar4; + uVar8 = DAT_TileMapState::instance.LogicLayer[iVar7]; + if (DAT_TileMapState::instance.WalkLayer[iVar7] != this->searchGeneration + && (uVar8 & 0x30) == 0) { + if ((uVar8 & 0x10000400) == 0) { + if ((uVar8 & 0x100) == 0) { + uVar8 = (uint)DAT_TileMapState::instance.HeightLayer[iVar7]; + if ((int)uVar8 <= (int)(uVar10 + param_5)) + goto LAB_004a63f4; + } else if ((DAT_TileMapState::instance.WallOwnerLayer[iVar7] & 7) + 1 == param_7) { + uVar8 = (uint)DAT_TileMapState::instance.HeightLayer[iVar7]; + LAB_004a63f4: + if ((int)uVar8 > (int)((param_5 * 2) / 3 + uVar10)) { + sVar5 = 3; + } else { + sVar5 = ((int)uVar8 > (int)(param_5 / 3 + uVar10)) + 1; + } + short sVar3 + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[iVar9] + .short_.xOffset; + DAT_TileMapState::instance.CertainPathLayer[iVar7] + = (short)this->searchQueue.currentDistance + sVar5; + DAT_TileMapState::instance.WalkLayer[iVar7] = (short)this->searchGeneration; + this->searchQueue.xQueue[this->searchQueue.writeIndex] = sVar3 + sVar1; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[iVar9] + .short_.yOffset + + sVar2; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = iVar7; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + } else { + int buildingID = (int)DAT_TileMapState::instance.BuildingLayer[iVar7]; + if ((buildingID != 0) + && (DAT_BuildingsState::instance.buildings[buildingID].owner == param_7)) { + uVar8 = MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func:: + getBuildingHeightForBuildingID, + DAT_BuildingsState::ptr)(buildingID); + goto LAB_004a63f4; + } + } + } + paiVar12 = (int (*)[3])(*paiVar12 + 1); + local_8 = local_8 - 1; + } while (local_8 != 0); + } + this->searchQueue.readIndex = this->searchQueue.readIndex + 1; + if (0x13a10 <= (int)this->searchQueue.readIndex) { + this->searchQueue.readIndex = 0; + } + } while (this->searchQueue.readIndex != this->searchQueue.writeIndex); + if (local_14 != -1) { + this->ALG_TargetX = local_14; + this->ALG_TargetTile = local_c; + this->ALG_TargetY = local_10; + } + } + return; + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/findBestAttackTileByPathCost.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/findBestAttackTileByPathCost.cpp new file mode 100644 index 0000000000..d889ec5b1b --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/findBestAttackTileByPathCost.cpp @@ -0,0 +1,120 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/IO/LowLevelMemory.func.hpp" +#include "OpenSHC/Map/Entities/EntityType.hpp" + +#include "OpenSHC/Globals/DAT_ClimbLogicDefinedData.hpp" +#include "OpenSHC/Globals/DAT_EntityState.hpp" +#include "OpenSHC/Globals/DAT_LowLevelMemory.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_TroopValueState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + + using OpenSHC::Map::Entities::EntityType; + + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + BFS from (param_1, param_2), scores reachable tiles against a hack values array (indexed by param_3) and a + target zone value (param_4). Returns the tile index with the lowest combined path cost and terrain cost + weighting. Used to select the optimal attack position for a unit approaching a target zone. renamed by: + Claude Sonnet 4.6 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x004A01D0 + dword PathFindingState::findBestAttackTileByPathCost(uint param_1, uint param_2, int param_3, uint param_4) + { + int iVar1; + dword dVar4 = 1000; + int local_4 = 1000; + dword local_8 = 0; + if (param_1 > 399 || param_2 > 399) { + return (dword)(dVar4); + } + if (DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[param_2 * 400 + param_1] == '\0') { + return (dword)(dVar4); + } + this->calculations = this->calculations + 1; + this->searchGeneration = this->searchGeneration + 1; + if (32000 < this->searchGeneration) { + this->searchGeneration = 1; + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 0x27420, '\0', (void*)((int)(DAT_TileMapState::instance.WalkLayer))); + } + this->searchQueue.readIndex = 0; + this->searchQueue.writeIndex = 1; + this->searchQueue.currentDistance = 1; + this->searchQueue.yQueue[0] = (short)param_2; + int _startTile = DAT_ViewportRenderState::instance.translationMatrix[param_2].addXgetTile + param_1; + this->searchQueue.tilesQueue[0] = _startTile; + DAT_TileMapState::instance.CertainPathLayer[_startTile] = (short)this->searchQueue.currentDistance; + DAT_TileMapState::instance.WalkLayer[this->searchQueue.tilesQueue[0]] = (short)this->searchGeneration; + dVar4 = local_8; + while (this->searchQueue.readIndex != this->searchQueue.writeIndex) { + int iVar3 = this->searchQueue.tilesQueue[this->searchQueue.readIndex]; + if (iVar3 < 0) { + return (dword)(local_8); + } + if (0x13a10 <= iVar3) { + return (dword)(local_8); + } + int sVar2 = (int)this->searchQueue.yQueue[this->searchQueue.readIndex]; + this->searchQueue.currentDistance = (int)DAT_TileMapState::instance.CertainPathLayer[iVar3]; + if (0x13a10 < (int)this->searchQueue.currentDistance) { + return (dword)(local_8); + } + for (int iVar5 = 0; iVar5 < 8; iVar5 = iVar5 + 1) { + if ((DAT_TileMapState::instance.PathLinkageLayer[iVar3] + & DAT_ClimbLogicDefinedData::instance.BitFlagHelperForPathLinkage[iVar5]) + != 0 + && (dVar4 = DAT_TileMapState::instance.directionTranslationMatrix[sVar2][iVar5] + iVar3, + DAT_TileMapState::instance.WalkLayer[dVar4] != this->searchGeneration)) { + if (((DAT_TileMapState::instance.EntityLayer[dVar4] == 0) + || (DAT_EntityState::instance.entityArray[DAT_TileMapState::instance.EntityLayer[dVar4]] + .entityType + != OpenSHC::Map::Entities::ET_FIRE)) + && DAT_TileMapState::instance.SEC_PathfindingCostTileMap1105[*( + int*)((int)DAT_TroopValueState::instance.attackInfo.hackValuesArray + + param_3 * 0x177bc + -0x10)][dVar4] + == param_4) { + if ((10 < (int)this->searchQueue.currentDistance) && (local_8 != 0)) { + return (dword)(local_8); + } + if ((6 < (int)this->searchQueue.currentDistance) + && (iVar1 = this->searchQueue.currentDistance + + (uint)DAT_TileMapState::instance.SEC_TileMap1104[dVar4] * 3, + iVar1 < local_4)) { + local_4 = iVar1; + local_8 = dVar4; + } + } + DAT_TileMapState::instance.CertainPathLayer[dVar4] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[dVar4] = (short)this->searchGeneration; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[iVar5].short_.yOffset + + sVar2; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = dVar4; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + } + this->searchQueue.readIndex = this->searchQueue.readIndex + 1; + if (0x13a10 <= (int)this->searchQueue.readIndex) { + this->searchQueue.readIndex = 0; + } + dVar4 = local_8; + } + return (dword)(dVar4); + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/findBuildingAccessPoint.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/findBuildingAccessPoint.cpp new file mode 100644 index 0000000000..050e0c67f7 --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/findBuildingAccessPoint.cpp @@ -0,0 +1,270 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/Map/Buildings/BuildingsState.func.hpp" +#include "OpenSHC/Map/Navigation/DirectionAlgorithmState.func.hpp" +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" +#include "OpenSHC/Map/Navigation/Algorithms/XYPair.hpp" + +#include "OpenSHC/Globals/DAT_BuildingDefinedData.hpp" +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_ClimbLogicDefinedData.hpp" +#include "OpenSHC/Globals/DAT_DirectionAlgorithmState.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_UnitsState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + using OpenSHC::Map::Navigation::Algorithms::XYPair; + + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + Function Summary: Find Building Access Point This function solves the problem: "Where should a unit walk to + interact with this building?" What It Does: Phase 1: Find All Valid Access Points Iterates through + predefined perimeter positions around the building Validates each position with three checks: Height + Check #1: Access tile within 32 units of building foundation Navigation Check: Unit can path to this area + Height Check #2: Access tile within 16 units of building's terrain height Phase 2: Choose Closest + Valid Point 3. Calculates distance from unit to each valid access point 4. Returns the closest one * + Finds the best accessible tile for a unit to approach a building. * This function determines where a unit + should walk to interact with a building * * Algorithm: * 1. Get all potential access points around + the building perimeter * 2. Filter by height compatibility (< 32 units from building base, < 16 from + terrain) * 3. Filter by navigation area connectivity * 4. Choose the closest valid access point to the + unit * * @param this - PathFindingState object pointer * @param unitID - ID of the unit trying to + access the building * @param buildingID - ID of the target building * @param param_3 - Output parameter: + returns the building tile adjacent to access point * @return Tile index of best access point, or 0 if none + found decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x004A8860 + int PathFindingState::findBuildingAccessPoint(int unitID, int buildingID, int* pResultTile) + { + int _canNav; + uint _heightDiff2; + int _candidate2; + XYPair* pXVar1; + int _closestDistance; + int _closestTile; + int _entranceCandidate; + int _counter; + int _accessibleIndex; + int _validAccessPointsCount; + int _limit; + int _pairsOfAccessAndAdjacent[200][2]; + int _accessibleTilesCount; + int _yOffset; + int _buidingDefHeight; + uint _buildingSize; + int _cHeight; + int _unitArea; + int _unitOwner; + /* + === GET BUILDING INFORMATION === + */ + int _buildingY = (int)(short)DAT_BuildingsState::instance.buildings[buildingID].y; + int _buildingX = (int)(short)DAT_BuildingsState::instance.buildings[buildingID].x; + /* + Get the default/base height of the building's foundation + */ + _buidingDefHeight + = DAT_TileMapState::instance.DefaultHeightLayer[DAT_BuildingsState::instance.buildings[buildingID] + .currentTilePositionAdjusted]; + /* + === GET UNIT INFORMATION === + */ + _unitArea + = (short)DAT_TileMapState::instance.PathConnectionLayer[DAT_UnitsState::instance.units[unitID].tile]; + _unitOwner = DAT_UnitsState::instance.units[unitID].owner; + /* + === GET BUILDING SIZE AND ACCESS POINT COUNT === + */ + _buildingSize = DAT_BuildingsState::instance.buildings[buildingID].widthOrHeight; + /* + Lookup table: building size -> number of accessible perimeter tiles Example: 2x2 building has 8 access + points, etc. + */ + _accessibleTilesCount = DAT_BuildingDefinedData::instance.BuildingAccessibleTilesCount[_buildingSize]; + /* + Count of valid access points found + */ + _validAccessPointsCount = 0; + /* + Current access point being checked + */ + _accessibleIndex = 0; + /* + Countdown for loop + */ + _limit = _accessibleTilesCount; + if (0 < _accessibleTilesCount) { + do { + /* + === PHASE 1: FIND ALL VALID ACCESS POINTS === Get the offset for this access point relative + to building origin This iterates through predefined perimeter positions + */ + MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::setupBuildingEntrancesOffset, + DAT_BuildingsState::ptr)(_buildingSize, 1, _accessibleIndex, 0); + _yOffset = DAT_BuildingsState::instance.DAT_TempYOffset; + /* + Calculate absolute tile position of this access point + */ + _entranceCandidate + = DAT_ViewportRenderState::instance + .translationMatrix[_buildingY + DAT_BuildingsState::instance.DAT_TempYOffset] + .addXgetTile + + DAT_BuildingsState::instance.DAT_TempXOffset + _buildingX; + /* + Get height of the access tile + */ + _cHeight = DAT_TileMapState::instance.HeightLayer[_entranceCandidate]; + uint _heightDiff = (uint)_buidingDefHeight - (uint)_cHeight; + /* + Compute absolute value: abs(_heightDiff) < 32 + */ + /* + === HEIGHT VALIDATION #1: Building Foundation Height === Check if access point is within 32 + height units of building base + */ + /* + === NAVIGATION AREA VALIDATION === Check if unit can reach this access point + */ + /* + === HEIGHT VALIDATION #2: Building Terrain Height === Check if access point is within 16 height + units of building's actual terrain height + */ + if (abs(_heightDiff) < 32 + && ((int)(short)DAT_TileMapState::instance.PathConnectionLayer[_entranceCandidate] == _unitArea + || (_canNav = MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func:: + calculateCanPlayerUnitsNavigateToAreaFromArea, + this)((int)_unitOwner, (dword)(_unitArea), + (dword)((int)(( + int)(short)DAT_TileMapState::instance.PathConnectionLayer[_entranceCandidate])), + 0), + _canNav != 0)) + && (_heightDiff2 + = (int)DAT_BuildingsState::instance.buildings[buildingID].terrainHeightUnk - (uint)_cHeight, + abs(_heightDiff2) < 16)) { + /* + === ACCESS POINT IS VALID - ADD TO LIST === Store the access tile + */ + _pairsOfAccessAndAdjacent[_validAccessPointsCount][0] = _entranceCandidate; + /* + Initialize adjacent building tile (will find next) + */ + _pairsOfAccessAndAdjacent[_validAccessPointsCount][1] = 0; + /* + === FIND ADJACENT BUILDING TILE === Search cardinal directions (horizontal first) to find + which building tile is adjacent to this access point + */ + pXVar1 = DAT_ClimbLogicDefinedData::instance.CardinalHorizontalFirstSearchOrder; + do { + _candidate2 + = DAT_ViewportRenderState::instance.translationMatrix[pXVar1->y + _yOffset + _buildingY] + .addXgetTile + + pXVar1->x + DAT_BuildingsState::instance.DAT_TempXOffset + _buildingX; + /* + Check if this tile belongs to our building + */ + if (DAT_TileMapState::instance.BuildingLayer[_candidate2] == buildingID) { + /* + Found it! Store the building tile adjacent to the access point + */ + _pairsOfAccessAndAdjacent[_validAccessPointsCount][1] = _candidate2; + break; + } + pXVar1 = pXVar1 + 1; + /* + Check all cardinal directions + */ + } while ((int)pXVar1 + < (int)&DAT_ClimbLogicDefinedData::instance.CardinalHorizontalFirstSearchOrder[4]); + /* + Increment valid access point count + */ + _validAccessPointsCount = _validAccessPointsCount + 1; + } + /* + Move to next access point + */ + _accessibleIndex = _accessibleIndex + 1; + if (_accessibleIndex >= _accessibleTilesCount) { + _accessibleIndex = 0; + } + _limit = _limit + -1; + } while (_limit != 0); + } + /* + === PHASE 2: CHOOSE CLOSEST ACCESS POINT === Loop counter + */ + _counter = 0; + /* + Index of best access point (-1 = none found) + */ + _closestTile = -1; + /* + Initialize output parameter + */ + *pResultTile = 0; + /* + Best distance so far (initialized to very large) + */ + _closestDistance = 10000; + /* + If we found any valid access points + */ + if (0 < _validAccessPointsCount) { + do { + /* + === CALCULATE DISTANCE FROM UNIT TO ACCESS POINT === Convert tile index back to X,Y + coordinates + */ + MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::DirectionAlgorithmState_Func::setAxisBasedDistanceResult, + DAT_DirectionAlgorithmState::ptr)((int)DAT_UnitsState::instance.units[unitID].x, + (int)(DAT_UnitsState::instance.units[unitID].y), + _pairsOfAccessAndAdjacent[_counter][0] + - DAT_ViewportRenderState::instance + .translationMatrix[DAT_ViewportRenderState::instance + .tileTranslationMatrix_YComponent[_pairsOfAccessAndAdjacent[_counter][0]]] + .addXgetTile, + (int)(DAT_ViewportRenderState::instance + .tileTranslationMatrix_YComponent[_pairsOfAccessAndAdjacent[_counter][0]])); + /* + If this access point is closer than previous best + */ + if (DAT_DirectionAlgorithmState::instance.distanceHigh < _closestDistance) { + /* + Update best distance + */ + /* + Remember this index + */ + _closestDistance = DAT_DirectionAlgorithmState::instance.distanceHigh; + _closestTile = _counter; + } + _counter = _counter + 1; + } while (_counter < _validAccessPointsCount); + /* + === RETURN BEST ACCESS POINT === + */ + if (_closestTile != -1) { + /* + Set output parameter: adjacent building tile + */ + *pResultTile = _pairsOfAccessAndAdjacent[_closestTile][1]; + /* + Return: access point tile + */ + return _pairsOfAccessAndAdjacent[_closestTile][0]; + } + } + /* + No valid access points found + */ + return 0; + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/findClosestFreeTileNearUnitOnBuilding.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/findClosestFreeTileNearUnitOnBuilding.cpp new file mode 100644 index 0000000000..e8a5e43691 --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/findClosestFreeTileNearUnitOnBuilding.cpp @@ -0,0 +1,122 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/IO/LowLevelMemory.func.hpp" +#include "OpenSHC/Map/Location/Point8ShortXY.hpp" + +#include "OpenSHC/Globals/DAT_LowLevelMemory.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_UnitsState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + using OpenSHC::Map::Location::Point8ShortXY; + + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x0049D880 + undefined4 PathFindingState::findClosestFreeTileNearUnitOnBuilding( + int buildingID, int unitID, int x, int y, int* pX, int* pY) + { + int (*paiVar4)[8]; + int iVar5; + int _lowestDist; + uint _tile; + int _unitArea; + int _x; + int _y; + this->searchGeneration = this->searchGeneration + 1; + this->calculations = this->calculations + 1; + _lowestDist = 10000; + if (32000 < this->searchGeneration) { + this->searchGeneration = 1; + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 0x27420, '\0', (void*)((int)(DAT_TileMapState::instance.WalkLayer))); + } + this->searchQueue.currentDistance = 1; + this->searchQueue.readIndex = 0; + this->searchQueue.writeIndex = 1; + _unitArea + = (short)DAT_TileMapState::instance.PathConnectionLayer[DAT_UnitsState::instance.units[unitID].tile]; + *pX = (int)DAT_UnitsState::instance.units[unitID].x; + *pY = (int)DAT_UnitsState::instance.units[unitID].y; + this->searchQueue.yQueue[0] = DAT_UnitsState::instance.units[unitID].y; + this->searchQueue.xQueue[0] = DAT_UnitsState::instance.units[unitID].x; + int _startTile = DAT_UnitsState::instance.units[unitID].tile; + this->searchQueue.tilesQueue[0] = _startTile; + DAT_TileMapState::instance.CertainPathLayer[_startTile] = (short)this->searchQueue.currentDistance; + DAT_TileMapState::instance.WalkLayer[this->searchQueue.tilesQueue[0]] = (short)this->searchGeneration; + if (this->searchQueue.readIndex != this->searchQueue.writeIndex) { + while (true) { + _tile = this->searchQueue.tilesQueue[this->searchQueue.readIndex]; + if (0x13a0f < _tile) { + return (undefined4)(1); + } + _x = (int)this->searchQueue.xQueue[this->searchQueue.readIndex]; + _y = (int)this->searchQueue.yQueue[this->searchQueue.readIndex]; + iVar5 = (int)_y; + int _absDistX = abs(_x - x); + int _absDistY = abs(iVar5 - y); + if (_absDistX > _absDistY) { + _absDistY = _absDistX; + } + if (_absDistY < _lowestDist) { + *pY = iVar5; + /* + lowest manhatten distance + */ + *pX = (int)_x; + _lowestDist = _absDistY; + } + this->searchQueue.currentDistance = (int)DAT_TileMapState::instance.CertainPathLayer[_tile]; + if (0x13a10 < (int)this->searchQueue.currentDistance) + break; + for (int _direction = 0; _direction < 8; _direction = _direction + 2) { + int _candidate + = DAT_TileMapState::instance.directionTranslationMatrix[iVar5][_direction] + _tile; + if (DAT_TileMapState::instance.WalkLayer[_candidate] != this->searchGeneration + && (short)DAT_TileMapState::instance.PathConnectionLayer[_candidate] == _unitArea + && DAT_TileMapState::instance.BuildingLayer[_candidate] == buildingID + && DAT_TileMapState::instance.UnitLayer[_candidate] == 0) { + /* + queue free spaces in the same area as the unit on the same building as the unit + */ + DAT_TileMapState::instance.CertainPathLayer[_candidate] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[_candidate] = (short)this->searchGeneration; + this->searchQueue.xQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction] + .short_.xOffset + + _x; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction] + .short_.yOffset + + _y; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = _candidate; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + } + + this->searchQueue.readIndex = this->searchQueue.readIndex + 1; + if (0x13a10 <= (int)this->searchQueue.readIndex) { + this->searchQueue.readIndex = 0; + } + if (this->searchQueue.readIndex == this->searchQueue.writeIndex) { + break; + } + } + } + return (undefined4)(1); + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/findClosestTileToStartingTile.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/findClosestTileToStartingTile.cpp new file mode 100644 index 0000000000..2fecdbcf5a --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/findClosestTileToStartingTile.cpp @@ -0,0 +1,53 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_TribesState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x00496EC0 + int PathFindingState::findClosestTileToStartingTile(int param_1) + { + int* _pResultTile; + int _match; + int _d; + int _closest; + int _tile; + int _startWalk = (short)DAT_TileMapState::instance.WalkLayer[this->searchQueue.tilesQueue[0]]; + int _startDistance + = (short)DAT_TileMapState::instance.CertainPathLayer[this->searchQueue.tilesQueue[0]]; + _closest = 4000; + _match = 0; + _pResultTile = this->searchQueue.tilesQueue + DAT_TribesState::instance.ALG_ResultTileIndex; + do { + _tile = *_pResultTile; + _d = (short)DAT_TileMapState::instance.CertainPathLayer[_tile]; + if (0 < _d && (_d - _startDistance) % param_1 == 0 && _d < _closest) { + _match = DAT_TribesState::instance.ALG_ResultTileIndex; + _closest = _d; + } + DAT_TribesState::instance.ALG_ResultTileIndex = DAT_TribesState::instance.ALG_ResultTileIndex + 1; + _pResultTile = _pResultTile + 1; + } while ((int)DAT_TribesState::instance.ALG_ResultTileIndex < 4000 + && (short)DAT_TileMapState::instance.WalkLayer[_tile] == _startWalk); + _tile = this->searchQueue.tilesQueue[_match]; + DAT_TribesState::instance.ALG_ResultY = (int)this->searchQueue.yQueue[_match]; + DAT_TribesState::instance.ALG_ResultTileIndex = _match; + DAT_TribesState::instance.ALG_ResultX = _tile + - DAT_ViewportRenderState::instance.translationMatrix[DAT_TribesState::instance.ALG_ResultY] + .addXgetTile; + return _tile; + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/findConnectingAreaBetweenTwoAreas.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/findConnectingAreaBetweenTwoAreas.cpp new file mode 100644 index 0000000000..710766fa26 --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/findConnectingAreaBetweenTwoAreas.cpp @@ -0,0 +1,172 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_GameState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + + /* + Graph search over active, recognised climb data entries to determine whether two path-connection areas + (param_2 and param_3) are reachable from each other via intermediate wall or building areas. Returns the + connecting intermediate area ID if a path exists, param_2 if they are directly adjacent, or 0 if no + connection is found. Used to decide if units can navigate between disconnected areas via climbing + structures. renamed by: Claude Sonnet 4.6 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x004A58A0 + dword PathFindingState::findConnectingAreaBetweenTwoAreas(int param_1, dword param_2, dword param_3) + { + undefined4 dVar2; + int iVar1; + int* piVar5; + int iVar6; + dword dVar7; + dword dVar8; + int local_96c; + int local_968; + dword adStack_960[200]; + int aiStack_640[400]; + if (param_2 == param_3) { + return (dword)(param_2); + } + this->DAT_Test_gatehouse = this->DAT_Test_gatehouse + 1; + local_96c = 0; + local_968 = 0; + iVar6 = 1; + if (1 < this->maxClimbDataCount) { + piVar5 = &this->climbData[1].isRecognizedByPathfinding; + do { + if (((ClimbData*)(piVar5 + -6))->canBeUsed == 1 && *piVar5 != 0 && piVar5[-5] != 1 + && ((param_1 == 0 + || (DAT_GameState::instance.mapAndTime.playerTeams[piVar5[0x73]] + == DAT_GameState::instance.mapAndTime.playerTeams[param_1])) + || (DAT_BuildingsState::instance.buildings[piVar5[-3]].field201_0x2c6 != 0))) { + aiStack_640[local_96c * 2 + 1] = 0; + aiStack_640[local_96c * 2] = iVar6; + local_96c = local_96c + 1; + } + iVar6 = iVar6 + 1; + piVar5 = piVar5 + 0x81; + } while (iVar6 < this->maxClimbDataCount); + } + int iVar4 = 0; + iVar6 = 0; + if (0 < local_96c) { + do { + iVar1 = aiStack_640[iVar4 * 2]; + dVar7 = this->climbData[iVar1].area; + if (dVar7 == param_3) { + dVar7 = this->climbData[iVar1].wallGroupAreaID; + if (dVar7 == param_2) { + return (dword)(param_3); + } + dVar8 = this->climbData[iVar1].buildingArea; + if (dVar8 == param_2) { + return (dword)(param_3); + } + adStack_960[iVar6] = dVar7; + iVar6 = iVar6 + 1; + aiStack_640[iVar4 * 2 + 1] = 1; + if (0 < (int)dVar8) { + adStack_960[iVar6] = dVar8; + iVar6 = iVar6 + 1; + } + } else if (this->climbData[iVar1].wallGroupAreaID == param_3) { + if (dVar7 == param_2) { + return (dword)(param_3); + } + dVar8 = this->climbData[iVar1].buildingArea; + if (dVar8 == param_2) { + return (dword)(param_3); + } + adStack_960[iVar6] = dVar7; + iVar6 = iVar6 + 1; + aiStack_640[iVar4 * 2 + 1] = 1; + if (0 < (int)dVar8) { + adStack_960[iVar6] = dVar8; + iVar6 = iVar6 + 1; + } + } else if (this->climbData[iVar1].buildingArea == param_3) { + dVar8 = this->climbData[iVar1].wallGroupAreaID; + if (dVar7 == param_2) { + return (dword)(param_3); + } + if (dVar8 == param_2) { + return (dword)(param_3); + } + adStack_960[iVar6] = dVar7; + iVar6 = iVar6 + 1; + aiStack_640[iVar4 * 2 + 1] = 1; + adStack_960[iVar6] = dVar8; + iVar6 = iVar6 + 1; + } + iVar4 = iVar4 + 1; + } while (iVar4 < local_96c); + if (0 < iVar6) { + do { + dVar7 = adStack_960[local_968]; + local_968 = local_968 + 1; + for (iVar4 = 0; iVar4 < local_96c; iVar4 = iVar4 + 1) { + if (aiStack_640[iVar4 * 2 + 1] == 1) { + continue; + } + iVar1 = aiStack_640[iVar4 * 2]; + dVar8 = this->climbData[iVar1].area; + if (dVar8 == dVar7) { + dVar8 = this->climbData[iVar1].wallGroupAreaID; + if (dVar8 == param_2) { + return (dword)(dVar7); + } + dVar2 = this->climbData[iVar1].buildingArea; + if (dVar2 == param_2) { + return (dword)(dVar7); + } + adStack_960[iVar6] = dVar8; + iVar6 = iVar6 + 1; + aiStack_640[iVar4 * 2 + 1] = 1; + if ((int)dVar2 <= 0) { + continue; + } + adStack_960[iVar6] = dVar2; + iVar6 = iVar6 + 1; + } else if (this->climbData[iVar1].wallGroupAreaID == dVar7) { + if (dVar8 == param_2) { + return (dword)(dVar7); + } + dVar2 = this->climbData[iVar1].buildingArea; + if (dVar2 == param_2) { + return (dword)(dVar7); + } + adStack_960[iVar6] = dVar8; + iVar6 = iVar6 + 1; + aiStack_640[iVar4 * 2 + 1] = 1; + if ((int)dVar2 <= 0) { + continue; + } + adStack_960[iVar6] = dVar2; + iVar6 = iVar6 + 1; + } else if (this->climbData[iVar1].buildingArea == dVar7) { + dVar2 = this->climbData[iVar1].wallGroupAreaID; + if (dVar8 == param_2) { + return (dword)(dVar7); + } + if (dVar2 == param_2) { + return (dword)(dVar7); + } + adStack_960[iVar6] = dVar8; + iVar6 = iVar6 + 1; + aiStack_640[iVar4 * 2 + 1] = 1; + adStack_960[iVar6] = dVar2; + iVar6 = iVar6 + 1; + } + } + } while (local_968 < iVar6); + } + } + return (dword)(0); + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/findCrossAreaBridgeTileToTarget.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/findCrossAreaBridgeTileToTarget.cpp new file mode 100644 index 0000000000..9a447af1e6 --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/findCrossAreaBridgeTileToTarget.cpp @@ -0,0 +1,145 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/IO/LowLevelMemory.func.hpp" +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" +#include "OpenSHC/Map/Location/Point8IntXY.hpp" + +#include "OpenSHC/Globals/DAT_LowLevelMemory.hpp" +#include "OpenSHC/Globals/DAT_PathFindingState.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_UnitsState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + using OpenSHC::Map::Location::Point8IntXY; + + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + BFS from unit param_1's current tile, expanding within its own PathConnectionLayer area or through + walls/structures. When a tile in a different area is encountered, checks whether that area connects to the + target area (param_2, param_3) via calculateCanPlayerUnitsNavigateToAreaFromArea. Selects the neighbour tile + with the minimum Chebyshev distance to the target. Stores the source tile in ALG_TargetTile and the bridge + tile in ALG_ResultTile. Returns 1 on success, 0 if no bridge found. renamed by: Claude Sonnet 4.6 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x004A6AB0 + undefined4 PathFindingState::findCrossAreaBridgeTileToTarget(int param_1, uint param_2, uint param_3) + { + int (*paiVar6)[8]; + int iVar7; + int iVar10; + int iVar13; + int local_20; + uint local_14; + int local_10; + local_14 = 0; + local_10 = 0; + local_20 = 10000; + if (param_2 > 399 || param_3 > 399 + || DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[param_3 * 400 + param_2] == '\0') { + return (undefined4)(0); + } + this->searchGeneration = this->searchGeneration + 1; + if (32000 < this->searchGeneration) { + this->searchGeneration = 1; + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 0x27420, '\0', (void*)((int)(DAT_TileMapState::instance.WalkLayer))); + } + this->searchQueue.currentDistance = 1; + this->searchQueue.writeIndex = 1; + this->searchQueue.readIndex = 0; + this->searchQueue.xQueue[0] = DAT_UnitsState::instance.units[param_1].x; + int uVar1 + = (short)DAT_TileMapState::instance.PathConnectionLayer[DAT_UnitsState::instance.units[param_1].tile]; + int uVar2 + = (short)DAT_TileMapState::instance + .PathConnectionLayer[DAT_ViewportRenderState::instance.translationMatrix[param_3].addXgetTile + + param_2]; + this->searchQueue.yQueue[0] = DAT_UnitsState::instance.units[param_1].y; + int _startTile = DAT_UnitsState::instance.units[param_1].tile; + this->searchQueue.tilesQueue[0] = _startTile; + DAT_TileMapState::instance.CertainPathLayer[_startTile] = 1; + DAT_TileMapState::instance.WalkLayer[this->searchQueue.tilesQueue[0]] = (short)this->searchGeneration; + if (this->searchQueue.readIndex != this->searchQueue.writeIndex) { + do { + uint uVar5 = this->searchQueue.tilesQueue[this->searchQueue.readIndex]; + if (0x13a0f < uVar5) + break; + int sVar3 = (int)this->searchQueue.xQueue[this->searchQueue.readIndex]; + int sVar4 = (int)this->searchQueue.yQueue[this->searchQueue.readIndex]; + this->searchQueue.currentDistance = (int)DAT_TileMapState::instance.CertainPathLayer[uVar5]; + if (0x13a10 < (int)this->searchQueue.currentDistance) + break; + for (int _direction = 0; _direction < 8; _direction = _direction + 2) { + iVar13 = DAT_TileMapState::instance.directionTranslationMatrix[sVar4][_direction] + uVar5; + if (DAT_TileMapState::instance.WalkLayer[iVar13] != this->searchGeneration + && (DAT_TileMapState::instance.LogicLayer[iVar13] & 0x400000U) == 0) { + if ((int)(short)DAT_TileMapState::instance.PathConnectionLayer[iVar13] == uVar1 + || (DAT_TileMapState::instance.LogicLayer[iVar13] & 0x10000100U) != 0) { + iVar7 = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction] + .int_.xOffset; + DAT_TileMapState::instance.WalkLayer[iVar13] = (short)this->searchGeneration; + DAT_TileMapState::instance.CertainPathLayer[iVar13] + = (short)this->searchQueue.currentDistance + 1; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = (short)DAT_TerrainDefinedData::instance + .clockwiseCardinalTranslationMatrix[_direction] + .int_.yOffset + + sVar4; + this->searchQueue.xQueue[this->searchQueue.writeIndex] = iVar7 + sVar3; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = iVar13; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } else { + iVar7 = MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func:: + calculateCanPlayerUnitsNavigateToAreaFromArea, + DAT_PathFindingState::ptr)((int)DAT_UnitsState::instance.units[param_1].owner, + (dword)((int)((short)DAT_TileMapState::instance.PathConnectionLayer[iVar13])), + (dword)(uVar2), (int)(DAT_UnitsState::instance.units[param_1].unitCanClimb)); + if (iVar7 != 0) { + iVar10 = abs( + (DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction] + .int_.yOffset + - param_3) + + (int)sVar4); + iVar7 = abs( + (DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction] + .int_.xOffset + - param_2) + + (int)sVar3); + if (iVar7 <= iVar10) { + iVar7 = iVar10; + } + if (iVar7 < local_20) { + local_20 = iVar7; + local_14 = uVar5; + local_10 = iVar13; + } + } + } + } + } + + this->searchQueue.readIndex = this->searchQueue.readIndex + 1; + if (0x13a10 <= (int)this->searchQueue.readIndex) { + this->searchQueue.readIndex = 0; + } + } while (this->searchQueue.readIndex != this->searchQueue.writeIndex); + if (local_20 < 10000) { + this->ALG_TargetTile = local_14; + this->ALG_ResultTile = local_10; + return (undefined4)(1); + } + } + return (undefined4)(0); + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/findDestinationCostLowerThan6.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/findDestinationCostLowerThan6.cpp new file mode 100644 index 0000000000..9bb5aa6132 --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/findDestinationCostLowerThan6.cpp @@ -0,0 +1,50 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x0049C5C0 + BOOLEnum PathFindingState::findDestinationCostLowerThan6(int tile, int maxDistance) + { + uint _cost; + this->searchQueue.readIndex = 0; + if (this->searchQueue.writeIndex != 0) { + byte* _pCost = DAT_TileMapState::instance.SEC_PathfindingCostTileMap1105[tile]; + do { + int _y = (int)this->searchQueue.yQueue[this->searchQueue.readIndex]; + int _tile = this->searchQueue.tilesQueue[this->searchQueue.readIndex]; + int _x = _tile - DAT_ViewportRenderState::instance.translationMatrix[_y].addXgetTile; + if (DAT_TileMapState::instance.WalkLayer[_tile] == this->searchGeneration + && (_cost = (uint)_pCost[_tile], _cost != 0) && _cost - 0x28 < 6 + && DAT_TileMapState::instance.CertainPathLayer[_tile] >= maxDistance) { + this->ALG_ResultX = _x; + this->ALG_ResultY = _y; + this->ALG_ResultTile = _tile; + return TRUE; + } + this->searchQueue.readIndex = this->searchQueue.readIndex + 1; + if (0x13a10 <= (int)this->searchQueue.readIndex) { + this->searchQueue.readIndex = 0; + } + } while (this->searchQueue.readIndex != this->searchQueue.writeIndex); + } + return FALSE; + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/findDirectNeighbourWalkableTile.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/findDirectNeighbourWalkableTile.cpp new file mode 100644 index 0000000000..6d6261e647 --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/findDirectNeighbourWalkableTile.cpp @@ -0,0 +1,58 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x0049CD60 + BOOLEnum PathFindingState::findDirectNeighbourWalkableTile(uint x, uint y) + { + if (x > 399 || y > 399) { + return FALSE; + } + if (DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[y * 400 + x] == '\0') { + return FALSE; + } + int _rowTile = DAT_ViewportRenderState::instance.translationMatrix[y].addXgetTile + x; + for (int _directionIndex = 0; _directionIndex < 8; _directionIndex = _directionIndex + 1) { + uint _x + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_directionIndex].int_.xOffset + + x; + uint _y + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_directionIndex].int_.yOffset + + y; + if (_x <= 399 && _y <= 399 + && DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[_y * 400 + _x] != '\0') { + int _tile = DAT_TileMapState::instance.directionTranslationMatrix[y][_directionIndex] + _rowTile; + if ((DAT_TileMapState::instance.LogicLayer[_tile] & 0xb1U) == 0 + && (DAT_TileMapState::instance.LogicLayer[_tile] & 0x50101400U) == 0) { + /* + No sea, borders, rocky, building, tree, river, keep, moat + */ + this->ALG_ResultY = _y; + this->ALG_ResultTile = _tile; + this->ALG_ResultX = _x; + return TRUE; + } + } + } + return FALSE; + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/findDistanceOrThreatLevelToUnitUnk.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/findDistanceOrThreatLevelToUnitUnk.cpp new file mode 100644 index 0000000000..50b1abf950 --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/findDistanceOrThreatLevelToUnitUnk.cpp @@ -0,0 +1,152 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/IO/LowLevelMemory.func.hpp" +#include "OpenSHC/Map/Units/UnitLogicState.hpp" + +#include "OpenSHC/Globals/DAT_GameState.hpp" +#include "OpenSHC/Globals/DAT_LowLevelMemory.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_UnitsState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + + using OpenSHC::Map::Units::UnitLogicState; + + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x004A0B20 + int PathFindingState::findDistanceOrThreatLevelToUnitUnk(int param_1, int param_2, int param_3, int param_4) + { + int (*paiVar3)[8]; + int iVar4; + int iVar5; + int local_c; + int local_8; + this->calculations = this->calculations + 1; + this->searchGeneration = this->searchGeneration + 1; + local_c = 0; + local_8 = 0; + if (32000 < this->searchGeneration) { + this->searchGeneration = 1; + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 0x27420, '\0', (void*)((int)(DAT_TileMapState::instance.WalkLayer))); + } + this->searchQueue.yQueue[0] = (short)param_3; + this->searchQueue.readIndex = 0; + this->searchQueue.writeIndex = 1; + this->searchQueue.currentDistance = 1; + int _startTile = DAT_ViewportRenderState::instance.translationMatrix[param_3].addXgetTile + param_2; + this->searchQueue.tilesQueue[0] = _startTile; + DAT_TileMapState::instance.CertainPathLayer[_startTile] = 1; + DAT_TileMapState::instance.WalkLayer[this->searchQueue.tilesQueue[0]] = (short)this->searchGeneration; + if (this->searchQueue.readIndex == this->searchQueue.writeIndex) { + return 0; + } + do { + uint uVar2 = this->searchQueue.tilesQueue[this->searchQueue.readIndex]; + if (0x13a0f < uVar2) { + return local_c; + } + int sVar1 = (int)this->searchQueue.yQueue[this->searchQueue.readIndex]; + this->searchQueue.currentDistance = (int)DAT_TileMapState::instance.CertainPathLayer[uVar2]; + if (0x13a10 < (int)this->searchQueue.currentDistance) { + return local_c; + } + if ((int)this->searchQueue.currentDistance > param_4) { + return local_c; + } + for (int _direction = 0; _direction < 8; _direction = _direction + 1) { + iVar4 = DAT_TileMapState::instance.directionTranslationMatrix[sVar1][_direction] + uVar2; + if ((DAT_TileMapState::instance.LogicLayer[iVar4] & 0x4a5014b1U) == 0 + && DAT_TileMapState::instance.WalkLayer[iVar4] != this->searchGeneration) { + iVar5 = (int)(short)DAT_TileMapState::instance.UnitLayer[iVar4]; + DAT_TileMapState::instance.CertainPathLayer[iVar4] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[iVar4] = (short)this->searchGeneration; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction] + .short_.yOffset + + sVar1; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = iVar4; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + if (iVar5 != 0 + && DAT_GameState::instance.mapAndTime.playerTeams[param_1] + != DAT_GameState::instance.mapAndTime + .playerTeams[DAT_UnitsState::instance.units[iVar5].owner] + && DAT_UnitsState::instance.units[iVar5].logicalState != OpenSHC::Map::Units::ULS_INVISIBLE + && DAT_UnitsState::instance.units[iVar5].dying == 0 + && DAT_UnitsState::instance.units[iVar5].isSelectable_OR_matchTime != 0) { + switch (DAT_UnitsState::instance.units[iVar5].unitType) { + case OpenSHC::Map::Units::UT_E_ARCHER: + case OpenSHC::Map::Units::UT_E_XBOW: + case OpenSHC::Map::Units::UT_A_ARCHER: + case OpenSHC::Map::Units::UT_A_HARCHER: + case OpenSHC::Map::Units::UT_S_FBALLISTA: + param_3 = 0xc; + break; + case OpenSHC::Map::Units::UT_E_SPEAR: + case OpenSHC::Map::Units::UT_E_LADDER: + case OpenSHC::Map::Units::UT_S_TOWER: + case OpenSHC::Map::Units::UT_S_BATTERINGRAM: + case OpenSHC::Map::Units::UT_S_SHIELD: + case OpenSHC::Map::Units::UT_A_SLAVE: + param_3 = 4; + break; + case OpenSHC::Map::Units::UT_E_PIKE: + case OpenSHC::Map::Units::UT_E_SWORD: + case OpenSHC::Map::Units::UT_E_KNIGHT: + case OpenSHC::Map::Units::UT_A_ASSASSIN: + case OpenSHC::Map::Units::UT_A_SWORDSMAN: + param_3 = 0; + break; + case OpenSHC::Map::Units::UT_E_MACE: + case OpenSHC::Map::Units::UT_E_MONK: + param_3 = 2; + break; + case OpenSHC::Map::Units::UT_E_ENGINEER: + case OpenSHC::Map::Units::UT_S_CATAPULT: + case OpenSHC::Map::Units::UT_A_FIRETHROWER: + param_3 = 0x14; + break; + case OpenSHC::Map::Units::UT_S_TREBUCHET: + param_3 = 0x1e; + break; + case OpenSHC::Map::Units::UT_S_MANGONEL: + case OpenSHC::Map::Units::UT_S_BALLISTA: + param_3 = 0x28; + break; + case OpenSHC::Map::Units::UT_LORD: + case OpenSHC::Map::Units::UT_A_SLINGER: + param_3 = 8; + } + param_3 = param_3 + 1 + this->searchQueue.currentDistance; + if (param_3 > local_8) { + local_8 = param_3; + local_c = iVar5; + } + } + } + } + + this->searchQueue.readIndex = this->searchQueue.readIndex + 1; + if (0x13a10 <= (int)this->searchQueue.readIndex) { + this->searchQueue.readIndex = 0; + } + } while (this->searchQueue.readIndex != this->searchQueue.writeIndex); + return local_c; + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/findFreeSpaceNextToEnemyDefensiveStructureInSameAreaWithinDistance.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/findFreeSpaceNextToEnemyDefensiveStructureInSameAreaWithinDistance.cpp new file mode 100644 index 0000000000..51ad48c387 --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/findFreeSpaceNextToEnemyDefensiveStructureInSameAreaWithinDistance.cpp @@ -0,0 +1,208 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/IO/LowLevelMemory.func.hpp" +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" +#include "OpenSHC/Map/Buildings/BuildingType.hpp" +#include "OpenSHC/Map/Buildings/BuildingTypeInt.hpp" +#include "OpenSHC/Map/Location/Point8ShortXY.hpp" +#include "OpenSHC/Map/Navigation/Algorithms/XYPair.hpp" + +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_ClimbLogicDefinedData.hpp" +#include "OpenSHC/Globals/DAT_GameState.hpp" +#include "OpenSHC/Globals/DAT_LowLevelMemory.hpp" +#include "OpenSHC/Globals/DAT_PathFindingState.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + + using OpenSHC::Map::Buildings::BuildingType; + using OpenSHC::Map::Buildings::BuildingTypeInt; + using OpenSHC::Map::Location::Point8ShortXY; + using OpenSHC::Map::Navigation::Algorithms::XYPair; + + /* + WARNING: Type propagation algorithm not settling + */ + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x004A7F50 + void PathFindingState::findFreeSpaceNextToEnemyDefensiveStructureInSameAreaWithinDistance( + int tile, int maxDestinations, int* area, int playerID, int shortenedDistance, int direction) + { + int iVar2; + int _candidate2; + int* piVar3; + XYPair* pXVar4; + BuildingTypeInt _buildingType; + int (*paiVar6)[8]; + int _candidate; + int _index; + int _dIndex; + int _maxDistance; + int _tile2; + short _origY; + int _origAXGT; + int _x; + int _y; + uint _tile; + _origY = (short)DAT_ViewportRenderState::instance.tileTranslationMatrix_YComponent[tile]; + _origAXGT = DAT_ViewportRenderState::instance.translationMatrix[_origY].addXgetTile; + _dIndex = 0; + _maxDistance = 10; + if (shortenedDistance == 1) { + _maxDistance = 3; + } + this->searchGeneration = this->searchGeneration + 1; + if (32000 < this->searchGeneration) { + this->searchGeneration = 1; + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 160800, '\0', (void*)((int)(DAT_TileMapState::instance.WalkLayer))); + } + maxDestinations = maxDestinations * 2; + if (500 < maxDestinations) { + maxDestinations = 500; + } else if (maxDestinations < 0x32) { + maxDestinations = 0x32; + } + this->searchQueue.writeIndex = 1; + this->searchQueue.currentDistance = 1; + this->searchQueue.readIndex = 0; + this->searchQueue.tilesQueue[0] = tile; + this->searchQueue.yQueue[0] = _origY; + DAT_TileMapState::instance.CertainPathLayer[tile] = (short)this->searchQueue.currentDistance; + this->searchQueue.xQueue[0] = tile - _origAXGT; + DAT_TileMapState::instance.WalkLayer[this->searchQueue.tilesQueue[0]] = (short)this->searchGeneration; + if (this->searchQueue.readIndex != this->searchQueue.writeIndex) { + while (_tile = this->searchQueue.tilesQueue[this->searchQueue.readIndex], _tile <= 0x13a0f) { + _x = (int)this->searchQueue.xQueue[this->searchQueue.readIndex]; + _y = (int)this->searchQueue.yQueue[this->searchQueue.readIndex]; + this->searchQueue.currentDistance = (int)DAT_TileMapState::instance.CertainPathLayer[_tile]; + if (80400 < (int)this->searchQueue.currentDistance + || (int)this->searchQueue.currentDistance > _maxDistance) + break; + for (int _direction = 0; _direction < 8; _direction = _direction + 1) { + _candidate = DAT_TileMapState::instance.directionTranslationMatrix[_y][_direction] + _tile; + if (DAT_TileMapState::instance.WalkLayer[_candidate] != this->searchGeneration + && (area == (int*)(int)(short)DAT_TileMapState::instance.PathConnectionLayer[_candidate] + || (iVar2 = MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func:: + calculateCanPlayerUnitsNavigateToAreaFromArea, + DAT_PathFindingState::ptr)(playerID, (dword)((int)(area)), + (dword)((int)(( + int)(short)DAT_TileMapState::instance.PathConnectionLayer[_candidate])), + 0), + iVar2 != 0))) { + short sVar1 + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction] + .short_.xOffset; + this->searchQueue.xQueue[this->searchQueue.writeIndex] = sVar1 + _x; + /* + queue tiles in same area that are pathable without climbing + */ + DAT_TileMapState::instance.CertainPathLayer[_candidate] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[_candidate] = (short)this->searchGeneration; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction] + .short_.yOffset + + _y; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = _candidate; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + } + + this->searchQueue.readIndex = this->searchQueue.readIndex + 1; + if (0x13a10 <= (int)this->searchQueue.readIndex) { + this->searchQueue.readIndex = 0; + } + if (this->searchQueue.readIndex == this->searchQueue.writeIndex) + break; + } + } + this->searchQueue.readIndex = 0; + if (0 < this->searchQueue.writeIndex) { + area = &this->searchQueue.destinationsArray[0].tile2OrAHelper; + do { + _tile2 = this->searchQueue.tilesQueue[this->searchQueue.readIndex]; + if ((DAT_TileMapState::instance.LogicLayer[_tile2] & 0x10000300U) == 0) { + _index = 0; + pXVar4 = DAT_ClimbLogicDefinedData::instance + .OrderedOrientationBasedCardinalDirectionList[direction]; + do { + _candidate2 = DAT_ViewportRenderState::instance + .translationMatrix[pXVar4->y + + (int)this->searchQueue.yQueue[this->searchQueue.readIndex]] + .addXgetTile + + ((XYPair*)&pXVar4->x)->x + (int)this->searchQueue.xQueue[this->searchQueue.readIndex]; + /* + if a wall gatehouse crenel keep and not a stockpile, and not a keep, and wall is of + enemy... break + */ + if ((DAT_TileMapState::instance.LogicLayer[_candidate2] & 0x10000300U) != 0 + && (DAT_TileMapState::instance.LogicLayer[_candidate2] & 2U) == 0 + && (DAT_TileMapState::instance.BuildingLayer[_candidate2] == 0 + || ((_buildingType = (BuildingTypeInt)(short)DAT_BuildingsState::instance + .buildings[DAT_TileMapState::instance.BuildingLayer[_candidate2]] + .buildingType, + _buildingType != OpenSHC::Map::Buildings::BT_STOCKPILE + && (2 < (uint)(_buildingType - OpenSHC::Map::Buildings::BT_MANORHOUSE))))) + && DAT_GameState::instance.mapAndTime + .playerTeams[(DAT_TileMapState::instance.WallOwnerLayer[_candidate2] & 7) + 1] + != DAT_GameState::instance.mapAndTime.playerTeams[playerID]) + break; + _candidate2 = 0; + _index = _index + 1; + pXVar4 = pXVar4 + 1; + } while (_index < 4); + if (((shortenedDistance != 1) + || ((short)DAT_TileMapState::instance.UnitLayer[_candidate2] == 0)) + && _candidate2 != 0) { + *area = _candidate2; + area[-1] = _tile2; + _dIndex = _dIndex + 1; + area = area + 3; + if (_dIndex >= maxDestinations) { + return; + } + this->searchQueue.tilesQueue[this->searchQueue.readIndex] = -1; + } + } + this->searchQueue.readIndex = this->searchQueue.readIndex + 1; + } while (this->searchQueue.readIndex < this->searchQueue.writeIndex); + } + this->searchQueue.readIndex = 0; + if (0 < this->searchQueue.writeIndex) { + piVar3 = &((PathFindingStatePartB*)(this->climbData + 200))->destinationsArray[_dIndex].tile2OrAHelper; + do { + iVar2 = this->searchQueue.tilesQueue[this->searchQueue.readIndex]; + if ((DAT_TileMapState::instance.LogicLayer[iVar2] & 0x10000300U) == 0 && iVar2 != -1) { + ((PathHelper12*)(piVar3 + -1))->tile1 = iVar2; + *piVar3 = 0; + _dIndex = _dIndex + 1; + piVar3 = piVar3 + 3; + if (maxDestinations <= _dIndex) { + return; + } + } + this->searchQueue.readIndex = this->searchQueue.readIndex + 1; + } while (this->searchQueue.readIndex < this->searchQueue.writeIndex); + } + this->searchQueue.destinationsArray[_dIndex].tile1 = 0; + ((PathFindingStatePartB*)(this->climbData + 200))->destinationsArray[_dIndex].tile2OrAHelper = 0; + return; + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/findFreeTileOnDefensiveStructure.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/findFreeTileOnDefensiveStructure.cpp new file mode 100644 index 0000000000..57d37e7111 --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/findFreeTileOnDefensiveStructure.cpp @@ -0,0 +1,119 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/IO/LowLevelMemory.func.hpp" +#include "OpenSHC/Map/Location/Point8ShortXY.hpp" + +#include "OpenSHC/Globals/DAT_LowLevelMemory.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + using OpenSHC::Map::Location::Point8ShortXY; + + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x0049D0E0 + void PathFindingState::findFreeTileOnDefensiveStructure(int unitID, int x, int y) + { + int (*paiVar4)[8]; + int iVar5; + int _tile; + this->calculations = this->calculations + 1; + this->ALG_ResultTile = 0; + this->ALG_ResultY = 0; + this->ALG_ResultX = 0; + if ((uint)x <= 399 && (uint)y <= 399 + && DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[y * 400 + x] != '\0') { + this->searchGeneration = this->searchGeneration + 1; + if (32000 < this->searchGeneration) { + this->searchGeneration = 1; + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 0x27420, '\0', (void*)((int)(DAT_TileMapState::instance.WalkLayer))); + } + this->searchQueue.readIndex = 0; + this->searchQueue.writeIndex = 1; + this->searchQueue.currentDistance = 1; + this->searchQueue.yQueue[0] = (short)y; + this->searchQueue.xQueue[0] = (short)x; + this->searchQueue.tilesQueue[0] + = DAT_ViewportRenderState::instance.translationMatrix[y].addXgetTile + x; + DAT_TileMapState::instance.WalkLayer[this->searchQueue.tilesQueue[0]] = (short)this->searchGeneration; + DAT_TileMapState::instance.CertainPathLayer[this->searchQueue.tilesQueue[0]] = 1; + if (this->searchQueue.readIndex != this->searchQueue.writeIndex) { + while (true) { + _tile = this->searchQueue.tilesQueue[this->searchQueue.readIndex]; + if (_tile < 0) { + break; + } + if (0x13a10 <= _tile) { + break; + } + int sVar1 = (int)this->searchQueue.xQueue[this->searchQueue.readIndex]; + int sVar2 = (int)this->searchQueue.yQueue[this->searchQueue.readIndex]; + iVar5 = (int)sVar2; + int _unitAtTile = (short)DAT_TileMapState::instance.UnitLayer[_tile]; + if (_unitAtTile == 0) { + this->ALG_ResultX = (int)sVar1; + this->ALG_ResultY = iVar5; + this->ALG_ResultTile = _tile; + return; + } + if (_unitAtTile == unitID) { + this->ALG_ResultX = (int)sVar1; + this->ALG_ResultY = iVar5; + this->ALG_ResultTile = _tile; + return; + } + this->searchQueue.currentDistance = (int)DAT_TileMapState::instance.CertainPathLayer[_tile]; + if (0x13a10 < (int)this->searchQueue.currentDistance) { + return; + } + for (int _direction = 0; _direction < 8; _direction = _direction + 2) { + iVar5 = DAT_TileMapState::instance.directionTranslationMatrix[sVar2][_direction] + _tile; + if (DAT_TileMapState::instance.WalkLayer[iVar5] != this->searchGeneration + && (DAT_TileMapState::instance.LogicLayer[iVar5] & 0x10000100U) != 0) { + /* + queue tiles that are wall gatehouse tower or keep + */ + DAT_TileMapState::instance.CertainPathLayer[iVar5] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[iVar5] = (short)this->searchGeneration; + this->searchQueue.xQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction] + .short_.xOffset + + sVar1; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = iVar5; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction] + .short_.yOffset + + sVar2; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + } + + this->searchQueue.readIndex = this->searchQueue.readIndex + 1; + if (0x13a10 <= (int)this->searchQueue.readIndex) { + this->searchQueue.readIndex = 0; + } + if (this->searchQueue.readIndex == this->searchQueue.writeIndex) { + return; + } + } + } + } + return; + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/findFurthestSeaTile.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/findFurthestSeaTile.cpp new file mode 100644 index 0000000000..a6360f269a --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/findFurthestSeaTile.cpp @@ -0,0 +1,108 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/IO/LowLevelMemory.func.hpp" +#include "OpenSHC/Map/Location/Point8ShortXY.hpp" + +#include "OpenSHC/Globals/DAT_LowLevelMemory.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + using OpenSHC::Map::Location::Point8ShortXY; + + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x0049BBF0 + void PathFindingState::findFurthestSeaTile(int budget, uint x, uint y) + { + int (*paiVar2)[8]; + int _x; + int _y; + this->ALG_ResultTile = 0; + this->ALG_ResultY = 0; + this->ALG_ResultX = 0; + if (x > 399 || y > 399) { + return; + } + if (DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[y * 400 + x] == '\0') { + return; + } + this->calculations = this->calculations + 1; + this->searchGeneration = this->searchGeneration + 1; + if (32000 < this->searchGeneration) { + this->searchGeneration = 1; + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 160800, '\0', (void*)((int)(DAT_TileMapState::instance.WalkLayer))); + } + this->searchQueue.readIndex = 0; + this->searchQueue.writeIndex = 1; + this->searchQueue.currentDistance = 1; + this->searchQueue.yQueue[0] = (short)y; + this->searchQueue.xQueue[0] = (short)x; + this->searchQueue.tilesQueue[0] = DAT_ViewportRenderState::instance.translationMatrix[y].addXgetTile + x; + DAT_TileMapState::instance.WalkLayer[this->searchQueue.tilesQueue[0]] = (short)this->searchGeneration; + DAT_TileMapState::instance.CertainPathLayer[this->searchQueue.tilesQueue[0]] = 1; + while (this->searchQueue.readIndex != this->searchQueue.writeIndex) { + this->ALG_ResultTile = this->searchQueue.tilesQueue[this->searchQueue.readIndex]; + if ((this->ALG_ResultTile < 0) || (0x13a10 <= this->ALG_ResultTile)) + break; + _y = (int)this->searchQueue.yQueue[this->searchQueue.readIndex]; + _x = (int)this->searchQueue.xQueue[this->searchQueue.readIndex]; + this->searchQueue.currentDistance + = (int)DAT_TileMapState::instance.CertainPathLayer[this->ALG_ResultTile]; + if (budget < this->searchQueue.writeIndex) { + this->ALG_ResultY = (int)_y; + this->ALG_ResultX = (int)_x; + return; + } + for (int _direction = 0; _direction < 8; _direction = _direction + 2) { + /* + for each direction, do: + */ + int _candidate + = DAT_TileMapState::instance.directionTranslationMatrix[_y][_direction] + this->ALG_ResultTile; + if (DAT_TileMapState::instance.WalkLayer[_candidate] != this->searchGeneration + && (DAT_TileMapState::instance.LogicLayer[_candidate] & 1) != 0) { + /* + is sea + */ + DAT_TileMapState::instance.CertainPathLayer[_candidate] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[_candidate] = (short)this->searchGeneration; + this->searchQueue.xQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction] + .short_.xOffset + + _x; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction] + .short_.yOffset + + _y; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = _candidate; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + } + + this->searchQueue.readIndex = this->searchQueue.readIndex + 1; + if (0x13a10 <= (int)this->searchQueue.readIndex) { + this->searchQueue.readIndex = 0; + } + } + this->ALG_ResultX = (int)this->searchQueue.yQueue[this->searchQueue.readIndex + 0x13a0f]; + this->ALG_ResultY = (int)this->searchQueue.yQueue[this->searchQueue.readIndex + -1]; + this->ALG_ResultTile = this->searchQueue.tilesQueue[this->searchQueue.readIndex + -1]; + return; + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/findLinkageBasedPathOrWalkRadius.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/findLinkageBasedPathOrWalkRadius.cpp new file mode 100644 index 0000000000..cd44b62c21 --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/findLinkageBasedPathOrWalkRadius.cpp @@ -0,0 +1,118 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/IO/LowLevelMemory.func.hpp" +#include "OpenSHC/Map/Navigation/PathFindingState/LinkageNeighbourAsm.hpp" +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +#include "OpenSHC/Globals/DAT_LowLevelMemory.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + * Performs BFS pathfinding for AI units to determine if a path exists between two points. * This is a fast + * "can reach" check rather than a full path reconstruction. * * Key features: * - Diagonal movement + * costs 2, cardinal movement costs 1 * - Can optionally reuse previous search state (for incremental + * searches) * - Returns immediately upon finding target (doesn't compute full distance map) * - Limited + * by param_5 (max search depth) * * @param this - PathFindingState object pointer * @param x - + * Starting X coordinate (0-399) * @param y - Starting Y coordinate (0-399) * @param x2 - Target X + * coordinate (0-399, or -1 for "search without target") * @param y2 - Target Y coordinate (0-399) * + * @param param_5 - Maximum search depth/distance limit * @param doNotIncrementSearchGeneration - If + * non-zero, continue previous search (incremental mode) * @return 1 if target is reachable, 0 otherwise + * decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x00497740 + BOOLEnum PathFindingState::findLinkageBasedPathOrWalkRadius( + uint x, uint y, int x2, int y2, int maxIterations, BOOLEnum continuePreviousSearch) + { + /* + === VALIDATE STARTING POSITION === Check bounds (400x400) and walkability + */ + if (399 < x || 399 < y) { + return FALSE; + } + if (DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[y * 400 + x] == '\0') { + return FALSE; + } + /* + === VALIDATE TARGET POSITION === If the target is given but invalid, cap the search depth at 500 + */ + if (x2 != -1 + && (399 < (uint)x2 || 399 < (uint)y2 + || DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[y2 * 400 + x2] == '\0') + && 500 < maxIterations) { + maxIterations = 500; + } + if (continuePreviousSearch == FALSE) { + this->searchGeneration = this->searchGeneration + 1; + if (32000 < this->searchGeneration) { + this->searchGeneration = 1; + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 0x27420, '\0', (void*)((int)(DAT_TileMapState::instance.WalkLayer))); + } + this->searchQueue.writeIndex = 1; + this->searchQueue.readIndex = 0; + this->searchQueue.depth = 0; + } + /* + The eight-neighbour expansion below is handwritten assembly in the original and reaches + the layers and the queue through these locals; see LinkageNeighbourAsm.hpp. The queue + indices and the target tile live in the parameter slots, as they do in the original. + */ + short _curGen = (short)this->searchGeneration; + short* _walkLayer = DAT_TileMapState::instance.WalkLayer; + short* _certainPath = DAT_TileMapState::instance.CertainPathLayer; + int* _tilesQueue = this->searchQueue.tilesQueue; + short* _yQueue = this->searchQueue.yQueue; + int* _dirMatrix = &DAT_TileMapState::instance.directionTranslationMatrix[0][0]; + uchar* _linkage = DAT_TileMapState::instance.PathLinkageLayer; + + this->searchQueue.yQueue[0] = (short)y; + this->searchQueue.tilesQueue[0] = DAT_ViewportRenderState::instance.translationMatrix[y].addXgetTile + x; + DAT_TileMapState::instance.CertainPathLayer[this->searchQueue.tilesQueue[0]] = 1; + DAT_TileMapState::instance.WalkLayer[this->searchQueue.tilesQueue[0]] = _curGen; + + y = this->searchQueue.writeIndex; + int _readIndex = this->searchQueue.readIndex; + continuePreviousSearch = this->searchQueue.depth; + if (x2 == -1) { + x = 0; + } else { + x = DAT_ViewportRenderState::instance.translationMatrix[y2].addXgetTile + x2; + } + int _result = 0; + while (_readIndex != (int)y && (int)continuePreviousSearch < maxIterations) { + continuePreviousSearch = continuePreviousSearch + 1; + int _tile = this->searchQueue.tilesQueue[_readIndex]; + if (_tile == (int)x) { + _result = 1; + break; + } + short _cCardinalDistance = _certainPath[_tile] + 1; + if (800 <= _cCardinalDistance) { + break; + } + int _cLink = _linkage[_tile]; + int _cY = (ushort)this->searchQueue.yQueue[_readIndex]; + + MACRO_LINKAGE_EXPAND_NEIGHBOURS(1, y) + + _readIndex = _readIndex + 1; + } + this->searchQueue.writeIndex = y; + this->searchQueue.readIndex = _readIndex; + this->searchQueue.depth = continuePreviousSearch; + return (BOOLEnum)_result; + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/findMapBorderEdgeTileAndStoreInSignpostData.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/findMapBorderEdgeTileAndStoreInSignpostData.cpp new file mode 100644 index 0000000000..2b4d8d96ca --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/findMapBorderEdgeTileAndStoreInSignpostData.cpp @@ -0,0 +1,141 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/IO/LowLevelMemory.func.hpp" + +#include "OpenSHC/Globals/DAT_ClimbLogicDefinedData.hpp" +#include "OpenSHC/Globals/DAT_GameState.hpp" +#include "OpenSHC/Globals/DAT_LowLevelMemory.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x0049B940 + void PathFindingState::findMapBorderEdgeTileAndStoreInSignpostData( + int signpostID, int maxDistance, uint x, uint y) + { + int (*paiVar1)[8]; + int _candidate; + int _index; + uint _tile; + int _x; + int _y; + DAT_GameState::instance.mapAndTime.signpostsMapEdgeDataCounter = 0; + this->calculations = this->calculations + 1; + this->resultTile = 0; + this->resultY = 0; + this->resultX = 0; + if (x > 399 || y > 399) { + return; + } + if (DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[y * 400 + x] == '\0') { + return; + } + this->searchGeneration = this->searchGeneration + 1; + if (32000 < this->searchGeneration) { + this->searchGeneration = 1; + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 0x27420, '\0', (void*)((int)(DAT_TileMapState::instance.WalkLayer))); + } + this->searchQueue.currentDistance = 1; + this->searchQueue.writeIndex = 1; + this->searchQueue.readIndex = 0; + this->searchQueue.yQueue[0] = (short)y; + this->searchQueue.xQueue[0] = (short)x; + int _startTile = DAT_ViewportRenderState::instance.translationMatrix[y].addXgetTile + x; + this->searchQueue.tilesQueue[0] = _startTile; + DAT_TileMapState::instance.CertainPathLayer[_startTile] = (short)this->searchQueue.currentDistance; + DAT_TileMapState::instance.WalkLayer[this->searchQueue.tilesQueue[0]] = (short)this->searchGeneration; + if (this->searchQueue.readIndex != this->searchQueue.writeIndex) { + while (_tile = this->searchQueue.tilesQueue[this->searchQueue.readIndex], (uint)_tile <= 0x13a0f) { + _x = (int)this->searchQueue.xQueue[this->searchQueue.readIndex]; + _y = (int)this->searchQueue.yQueue[this->searchQueue.readIndex]; + this->searchQueue.currentDistance = (int)DAT_TileMapState::instance.CertainPathLayer[_tile]; + if ((int)this->searchQueue.currentDistance > maxDistance) { + return; + } + _index = 0; + paiVar1 = DAT_TileMapState::instance.directionTranslationMatrix + _y; + do { + /* + for each direction, do + */ + _candidate = (*paiVar1)[0] + _tile; + if (DAT_TileMapState::instance.WalkLayer[_candidate] != this->searchGeneration) { + /* + reached map border edge? + */ + if ((DAT_TileMapState::instance.LogicLayer[_candidate] & 0x30) != 0) { + this->resultX = (int)_x; + this->resultY = (int)_y; + this->resultTile = _tile; + DAT_GameState::instance.mapAndTime + .signpostsMapEdge[signpostID] + [DAT_GameState::instance.mapAndTime.signpostsMapEdgeDataCounter] + .x = (int)_x; + DAT_GameState::instance.mapAndTime + .signpostsMapEdge[signpostID] + [DAT_GameState::instance.mapAndTime.signpostsMapEdgeDataCounter] + .y = this->resultY; + DAT_GameState::instance.mapAndTime + .signpostsMapEdge[signpostID] + [DAT_GameState::instance.mapAndTime.signpostsMapEdgeDataCounter] + .tile = this->resultTile; + DAT_GameState::instance.mapAndTime.signpostsMapEdgeDataCounter + = DAT_GameState::instance.mapAndTime.signpostsMapEdgeDataCounter + 1; + if (DAT_GameState::instance.mapAndTime.signpostsMapEdgeDataCounter >= 50) { + return; + } + break; + } + if ((DAT_TileMapState::instance.PathLinkageLayer[_tile] + & DAT_ClimbLogicDefinedData::instance.BitFlagHelperForPathLinkage[_index]) + != 0) { + /* + this direction can be walked to? add to queue + */ + DAT_TileMapState::instance.CertainPathLayer[_candidate] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[_candidate] = (short)this->searchGeneration; + this->searchQueue.xQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_index] + .short_.xOffset + + _x; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_index] + .short_.yOffset + + _y; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = _candidate; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + } + _index = _index + 2; + paiVar1 = (int (*)[8])(*paiVar1 + 2); + } while (_index < 8); + this->searchQueue.readIndex = this->searchQueue.readIndex + 1; + if (0x13a10 <= (int)this->searchQueue.readIndex) { + this->searchQueue.readIndex = 0; + } + if (this->searchQueue.readIndex == this->searchQueue.writeIndex) { + return; + } + } + } + return; + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/findNearestEnemyBuildingWithinDistance.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/findNearestEnemyBuildingWithinDistance.cpp new file mode 100644 index 0000000000..63d122162d --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/findNearestEnemyBuildingWithinDistance.cpp @@ -0,0 +1,112 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/IO/LowLevelMemory.func.hpp" +#include "OpenSHC/Map/Buildings/BuildingsState.func.hpp" +#include "OpenSHC/Map/Buildings/BuildingLogicalState.hpp" +#include "OpenSHC/Map/Buildings/BuildingLogicalStateShort.hpp" + +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_GameState.hpp" +#include "OpenSHC/Globals/DAT_LowLevelMemory.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + + using OpenSHC::Map::Buildings::BuildingLogicalState; + using OpenSHC::Map::Buildings::BuildingLogicalStateShort; + + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + BFS from (param_2, param_3) up to distance param_4, checking each visited tile's BuildingLayer. Returns the + building ID of the first reachable enemy building (different team to param_1) that is alive (logicalState != + 0 and != 3), not on fire, and has a valid fire-related building parameter. Returns 0 if none found. renamed + by: Claude Sonnet 4.6 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x004A0460 + int PathFindingState::findNearestEnemyBuildingWithinDistance(int param_1, int param_2, int param_3, int param_4) + { + BuildingLogicalStateShort BVar2; + int iVar3; + int iVar5; + int (*paiVar6)[8]; + this->searchGeneration = this->searchGeneration + 1; + this->calculations = this->calculations + 1; + if (32000 < this->searchGeneration) { + this->searchGeneration = 1; + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 0x27420, '\0', (void*)((int)(DAT_TileMapState::instance.WalkLayer))); + } + this->searchQueue.yQueue[0] = (short)param_3; + this->searchQueue.readIndex = 0; + this->searchQueue.writeIndex = 1; + this->searchQueue.currentDistance = 1; + this->searchQueue.tilesQueue[0] + = DAT_ViewportRenderState::instance.translationMatrix[param_3].addXgetTile + param_2; + DAT_TileMapState::instance.WalkLayer[this->searchQueue.tilesQueue[0]] = (short)this->searchGeneration; + DAT_TileMapState::instance.CertainPathLayer[this->searchQueue.tilesQueue[0]] = 1; + if (this->searchQueue.readIndex != this->searchQueue.writeIndex) { + while ((iVar3 = this->searchQueue.tilesQueue[this->searchQueue.readIndex], + -1 < iVar3 && (iVar3 < 0x13a10))) { + int sVar1 = (int)this->searchQueue.yQueue[this->searchQueue.readIndex]; + this->searchQueue.currentDistance = (int)DAT_TileMapState::instance.CertainPathLayer[iVar3]; + if (0x13a10 < (int)this->searchQueue.currentDistance) { + return 0; + } + if ((int)this->searchQueue.currentDistance > param_4) { + return 0; + } + for (int _direction = 0; _direction < 8; _direction = _direction + 1) { + int iVar4 = DAT_TileMapState::instance.directionTranslationMatrix[sVar1][_direction] + iVar3; + if ((DAT_TileMapState::instance.LogicLayer[iVar4] & 0x30) == 0 + && DAT_TileMapState::instance.WalkLayer[iVar4] != this->searchGeneration) { + DAT_TileMapState::instance.CertainPathLayer[iVar4] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[iVar4] = (short)this->searchGeneration; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = iVar4; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction] + .short_.yOffset + + sVar1; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + iVar4 = (int)DAT_TileMapState::instance.BuildingLayer[iVar4]; + if (iVar4 != 0 + && DAT_GameState::instance.mapAndTime.playerTeams[param_1] + != DAT_GameState::instance.mapAndTime + .playerTeams[DAT_BuildingsState::instance.buildings[iVar4].owner] + && (BVar2 = DAT_BuildingsState::instance.buildings[iVar4].logicalState, + BVar2 != ((BuildingLogicalState)0)) + && BVar2 != OpenSHC::Map::Buildings::BLS_REMOVE + && DAT_BuildingsState::instance.buildings[iVar4].fireDuration == 0 + && (iVar5 = MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::getBuildingFlammabilityFactor, + DAT_BuildingsState::ptr)(iVar4), + iVar5 != 0 && (iVar5 != 4))) { + return iVar4; + } + } + } + + this->searchQueue.readIndex = this->searchQueue.readIndex + 1; + if (0x13a10 <= (int)this->searchQueue.readIndex) { + this->searchQueue.readIndex = 0; + } + if (this->searchQueue.readIndex == this->searchQueue.writeIndex) { + return 0; + } + } + } + return 0; + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/findNearestEnemyUnitWithinDistance.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/findNearestEnemyUnitWithinDistance.cpp new file mode 100644 index 0000000000..60ec156079 --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/findNearestEnemyUnitWithinDistance.cpp @@ -0,0 +1,106 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/IO/LowLevelMemory.func.hpp" +#include "OpenSHC/Map/Units/UnitLogicState.hpp" +#include "OpenSHC/Map/Units/UnitLogicStateShort.hpp" + +#include "OpenSHC/Globals/DAT_GameState.hpp" +#include "OpenSHC/Globals/DAT_LowLevelMemory.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_UnitsState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + + using OpenSHC::Map::Units::UnitLogicState; + using OpenSHC::Map::Units::UnitLogicStateShort; + + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + Structurally identical to findNearestEnemyBuildingWithinDistance but checks UnitLayer instead of + BuildingLayer. BFS from (param_2, param_3) up to distance param_4, returns the unit ID of the first + reachable live enemy unit (different team to param_1) that is not invisible, not flagged for removal, and + not dying. Returns 0 if none found. renamed by: Claude Sonnet 4.6 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x004A06B0 + int PathFindingState::findNearestEnemyUnitWithinDistance(int param_1, int param_2, int param_3, int param_4) + { + UnitLogicStateShort UVar2; + int iVar3; + int (*paiVar6)[8]; + this->searchGeneration = this->searchGeneration + 1; + this->calculations = this->calculations + 1; + if (32000 < this->searchGeneration) { + this->searchGeneration = 1; + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 0x27420, '\0', (void*)((int)(DAT_TileMapState::instance.WalkLayer))); + } + this->searchQueue.yQueue[0] = (short)param_3; + this->searchQueue.readIndex = 0; + this->searchQueue.writeIndex = 1; + this->searchQueue.currentDistance = 1; + this->searchQueue.tilesQueue[0] + = DAT_ViewportRenderState::instance.translationMatrix[param_3].addXgetTile + param_2; + DAT_TileMapState::instance.WalkLayer[this->searchQueue.tilesQueue[0]] = (short)this->searchGeneration; + DAT_TileMapState::instance.CertainPathLayer[this->searchQueue.tilesQueue[0]] = 1; + if (this->searchQueue.readIndex != this->searchQueue.writeIndex) { + while ((iVar3 = this->searchQueue.tilesQueue[this->searchQueue.readIndex], + -1 < iVar3 && (iVar3 < 0x13a10))) { + short sVar1 = this->searchQueue.yQueue[this->searchQueue.readIndex]; + this->searchQueue.currentDistance = (int)DAT_TileMapState::instance.CertainPathLayer[iVar3]; + if (0x13a10 < (int)this->searchQueue.currentDistance) { + return 0; + } + if ((int)this->searchQueue.currentDistance > param_4) { + return 0; + } + for (int _direction = 0; _direction < 8; _direction = _direction + 1) { + int iVar4 = DAT_TileMapState::instance.directionTranslationMatrix[sVar1][_direction] + iVar3; + if ((DAT_TileMapState::instance.LogicLayer[iVar4] & 0x30) == 0 + && DAT_TileMapState::instance.WalkLayer[iVar4] != this->searchGeneration) { + DAT_TileMapState::instance.CertainPathLayer[iVar4] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[iVar4] = (short)this->searchGeneration; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction] + .short_.yOffset + + sVar1; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = iVar4; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + iVar4 = (int)(short)DAT_TileMapState::instance.UnitLayer[iVar4]; + if (iVar4 != 0 + && DAT_GameState::instance.mapAndTime.playerTeams[param_1] + != DAT_GameState::instance.mapAndTime + .playerTeams[DAT_UnitsState::instance.units[iVar4].owner] + && (UVar2 = DAT_UnitsState::instance.units[iVar4].logicalState, + UVar2 != OpenSHC::Map::Units::ULS_INVISIBLE) + && UVar2 != OpenSHC::Map::Units::ULS_REMOVE + && DAT_UnitsState::instance.units[iVar4].dying == 0) { + return iVar4; + } + } + } + + this->searchQueue.readIndex = this->searchQueue.readIndex + 1; + if (0x13a10 <= (int)this->searchQueue.readIndex) { + this->searchQueue.readIndex = 0; + } + if (this->searchQueue.readIndex == this->searchQueue.writeIndex) { + return 0; + } + } + } + return 0; + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/findNeighbourTileThatCanServeAsClimbPointClosestToXY.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/findNeighbourTileThatCanServeAsClimbPointClosestToXY.cpp new file mode 100644 index 0000000000..52f6a7c462 --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/findNeighbourTileThatCanServeAsClimbPointClosestToXY.cpp @@ -0,0 +1,117 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/Map/Buildings/BuildingsState.func.hpp" +#include "OpenSHC/Map/Navigation/DirectionAlgorithmState.func.hpp" +#include "OpenSHC/Map/Location/Point8IntXY.hpp" + +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_DirectionAlgorithmState.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + using OpenSHC::Map::Location::Point8IntXY; + + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x004974D0 + BOOL PathFindingState::findNeighbourTileThatCanServeAsClimbPointClosestToXY(uint x, uint y, uint x2, uint y2) + { + int iVar2; + int (*paiVar3)[8]; + int _candidate2; + int _tile2; + uint _c2Height; + int _minDistance; + BOOL _status; + ushort _area1; + uint uVar1 = y2; + if (399 < x || 399 < y) { + return 0; + } + if (DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[y * 400 + x] == '\0') { + return 0; + } + if (x2 <= 399 && y2 <= 399 + && DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[y2 * 400 + x2] != '\0') { + _tile2 = DAT_ViewportRenderState::instance.translationMatrix[y2].addXgetTile + x2; + /* + height 2 + */ + y2 = (uint)DAT_TileMapState::instance.HeightLayer[_tile2]; + _area1 + = DAT_TileMapState::instance + .PathConnectionLayer[DAT_ViewportRenderState::instance.translationMatrix[y].addXgetTile + x]; + _status = 0; + _minDistance = 1000; + if (DAT_TileMapState::instance.BuildingLayer[_tile2] != 0) { + /* + add building height to height2 + */ + iVar2 = MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::getBuildingHeightForBuildingID, + DAT_BuildingsState::ptr)((int)DAT_TileMapState::instance.BuildingLayer[_tile2]); + y2 = y2 + iVar2; + } + for (int _direction = 0; _direction < 8; _direction = _direction + 1) { + /* + for each direction relative to tile 2, do + */ + _candidate2 = DAT_TileMapState::instance.directionTranslationMatrix[uVar1][_direction] + _tile2; + if ((short)DAT_TileMapState::instance.PathConnectionLayer[_candidate2] == _area1 + && (short)DAT_TileMapState::instance.UnitLayer[_candidate2] == 0) { + /* + area is same as area1, no units on this tile compute the total height at this candidate tile + */ + _c2Height = (uint)DAT_TileMapState::instance.HeightLayer[_candidate2]; + if (DAT_TileMapState::instance.BuildingLayer[_candidate2] != 0) { + iVar2 = MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::getBuildingHeightForBuildingID, + DAT_BuildingsState::ptr)((int)DAT_TileMapState::instance.BuildingLayer[_candidate2]); + _c2Height = _c2Height + iVar2; + } + if ((int)y2 <= (int)(_c2Height + 16) && (int)y2 >= (int)(_c2Height - 16)) { + /* + if the height of this candidate tile is within 16 of the tile2 height then, compute the + distance between x,y and the candidate2 tile + */ + MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::DirectionAlgorithmState_Func::setAxisBasedDistanceResult, + DAT_DirectionAlgorithmState::ptr)(x, (int)(y), + (int)(DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction] + .int_.xOffset + + x2), + (int)(DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction] + .int_.yOffset + + uVar1)); + if (DAT_DirectionAlgorithmState::instance.distanceHigh < _minDistance) { + this->climbX + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction] + .int_.xOffset + + x2; + this->climbY + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction] + .int_.yOffset + + uVar1; + _minDistance = DAT_DirectionAlgorithmState::instance.distanceHigh; + _status = 1; + } + } + } + } + + return _status; + } + return 0; + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/findNextTileByModuloAmongPreviousSearchNotOnDefensiveStructure.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/findNextTileByModuloAmongPreviousSearchNotOnDefensiveStructure.cpp new file mode 100644 index 0000000000..3a77a62bb5 --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/findNextTileByModuloAmongPreviousSearchNotOnDefensiveStructure.cpp @@ -0,0 +1,59 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_TribesState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x00497180 + dword PathFindingState::findNextTileByModuloAmongPreviousSearchNotOnDefensiveStructure(int modulo, int x, int y) + { + uint _xDistance; + uint _yDistance; + int* _pTile; + int iVar1; + dword _result; + int _tile; + int _startWalk = (short)DAT_TileMapState::instance.WalkLayer[this->searchQueue.tilesQueue[0]]; + _pTile = this->searchQueue.tilesQueue + DAT_TribesState::instance.ALG_ResultTileIndex; + iVar1 = DAT_TribesState::instance.ALG_ResultTileIndex; + while (true) { + _tile = *_pTile; + /* + manhatten distance + */ + int _tileY = (short)DAT_ViewportRenderState::instance.tileTranslationMatrix_YComponent[_tile]; + int _distance = (short)DAT_TileMapState::instance.CertainPathLayer[_tile]; + if ((DAT_TileMapState::instance.LogicLayer[_tile] & 0x10000100U) == 0 && 0 < _distance + && (_xDistance + = (_tile - DAT_ViewportRenderState::instance.translationMatrix[_tileY].addXgetTile) - x, + _yDistance = _tileY - y, (abs(_yDistance) + abs(_xDistance)) % modulo == 0) + && _distance < 4000) + break; + iVar1 = iVar1 + 1; + _pTile = _pTile + 1; + if (4000 < iVar1 || (short)DAT_TileMapState::instance.WalkLayer[_tile] != _startWalk) { + return (dword)(0); + } + } + _result = this->searchQueue.tilesQueue[iVar1]; + DAT_TribesState::instance.ALG_ResultY = (int)this->searchQueue.yQueue[iVar1]; + DAT_TribesState::instance.ALG_ResultTileIndex = iVar1; + DAT_TribesState::instance.ALG_ResultX = _result + - DAT_ViewportRenderState::instance.translationMatrix[DAT_TribesState::instance.ALG_ResultY] + .addXgetTile; + return (dword)(_result); + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/findNextTileInExistingSearchThatIsModuloDistanceAway.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/findNextTileInExistingSearchThatIsModuloDistanceAway.cpp new file mode 100644 index 0000000000..399e8770c5 --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/findNextTileInExistingSearchThatIsModuloDistanceAway.cpp @@ -0,0 +1,55 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_TribesState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x00496F90 + void PathFindingState::findNextTileInExistingSearchThatIsModuloDistanceAway(int modulo, int x, int y) + { + int iVar2; + int _dx; + int _dy; + int* _pLastTile; + int local_10; + local_10 = 0; + _pLastTile = this->searchQueue.tilesQueue + DAT_TribesState::instance.ALG_ResultTileIndex; + while (true) { + int iVar1 = *_pLastTile; + int _tileY = (short)DAT_ViewportRenderState::instance.tileTranslationMatrix_YComponent[iVar1]; + int _dist = DAT_TileMapState::instance.CertainPathLayer[iVar1]; + if (0 < _dist + && (_dx = (iVar1 - DAT_ViewportRenderState::instance.translationMatrix[_tileY].addXgetTile) - x, + _dy = _tileY - y, (abs(_dy) + abs(_dx)) % modulo == 0) + && (iVar2 = DAT_TribesState::instance.ALG_ResultTileIndex, _dist < 4000)) + break; + DAT_TribesState::instance.ALG_ResultTileIndex = DAT_TribesState::instance.ALG_ResultTileIndex + 1; + _pLastTile = _pLastTile + 1; + iVar2 = local_10; + if ((4000 < DAT_TribesState::instance.ALG_ResultTileIndex) + || (DAT_TileMapState::instance.WalkLayer[iVar1] + != DAT_TileMapState::instance.WalkLayer[this->searchQueue.tilesQueue[0]])) + break; + } + local_10 = iVar2; + DAT_TribesState::instance.ALG_ResultY = (int)this->searchQueue.yQueue[local_10]; + DAT_TribesState::instance.ALG_ResultX = this->searchQueue.tilesQueue[local_10] + - DAT_ViewportRenderState::instance.translationMatrix[DAT_TribesState::instance.ALG_ResultY] + .addXgetTile; + DAT_TribesState::instance.ALG_ResultTileIndex = local_10; + return; + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/findNoTreeInRange.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/findNoTreeInRange.cpp new file mode 100644 index 0000000000..d523489e4f --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/findNoTreeInRange.cpp @@ -0,0 +1,130 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/IO/LowLevelMemory.func.hpp" +#include "OpenSHC/Map/Trees/TreeType.hpp" +#include "OpenSHC/Map/Trees/TreeTypeShort.hpp" +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +#include "OpenSHC/Globals/DAT_LandscapeState.hpp" +#include "OpenSHC/Globals/DAT_LowLevelMemory.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + + using OpenSHC::Map::Trees::TreeType; + using OpenSHC::Map::Trees::TreeTypeShort; + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x0049C370 + BOOLEnum PathFindingState::findNoTreeInRange(int budget, uint x, uint y) + { + int (*paiVar2)[8]; + int _tile; + TreeTypeShort _treeType; + this->ALG_ResultTile = 0; + this->ALG_ResultY = 0; + this->ALG_ResultX = 0; + if (399 < x || 399 < y) { + return FALSE; + } + if (DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[y * 400 + x] == '\0') { + return FALSE; + } + this->calculations = this->calculations + 1; + this->searchGeneration = this->searchGeneration + 1; + if (32000 < this->searchGeneration) { + this->searchGeneration = 1; + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 0x27420, '\0', (void*)((int)(DAT_TileMapState::instance.WalkLayer))); + } + this->searchQueue.readIndex = 0; + this->searchQueue.writeIndex = 1; + this->searchQueue.currentDistance = 1; + this->searchQueue.yQueue[0] = (short)y; + this->searchQueue.tilesQueue[0] = DAT_ViewportRenderState::instance.translationMatrix[y].addXgetTile + x; + DAT_TileMapState::instance.WalkLayer[this->searchQueue.tilesQueue[0]] = (short)this->searchGeneration; + DAT_TileMapState::instance.CertainPathLayer[this->searchQueue.tilesQueue[0]] = 1; + if (this->searchQueue.readIndex != this->searchQueue.writeIndex) { + while (true) { + _tile = this->searchQueue.tilesQueue[this->searchQueue.readIndex]; + if (_tile < 0) { + break; + } + if (0x13a10 <= _tile) { + break; + } + this->searchQueue.currentDistance = (int)DAT_TileMapState::instance.CertainPathLayer[_tile]; + if ((int)this->searchQueue.currentDistance > budget) { + return TRUE; + } + int sVar1 = (int)this->searchQueue.yQueue[this->searchQueue.readIndex]; + for (int _direction = 0; _direction < 8; _direction = _direction + 1) { + /* + for each direction, do: + */ + int _candidate + = DAT_TileMapState::instance.directionTranslationMatrix[sVar1][_direction] + _tile; + if (DAT_TileMapState::instance.WalkLayer[_candidate] != this->searchGeneration) { + int _org = (int)DAT_TileMapState::instance.OrganismLayer[_candidate]; + if ((_org == 0) || (1999 < _org)) { + if ((DAT_TileMapState::instance.LogicLayer[_candidate] & 0x30) == 0) { + /* + not map edge? add to queue + */ + DAT_TileMapState::instance.CertainPathLayer[_candidate] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[_candidate] = (short)this->searchGeneration; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = _candidate; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance + .clockwiseCardinalTranslationMatrix[_direction] + .short_.yOffset + + sVar1; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + } else { + _treeType = DAT_LandscapeState::instance.trees[_org].treeType; + if (_treeType == (TreeType)1) { + return FALSE; + } + if (_treeType == (TreeType)2) { + return FALSE; + } + if (_treeType == (TreeType)3) { + return FALSE; + } + if (_treeType == (TreeType)4) { + return FALSE; + } + } + } + } + + this->searchQueue.readIndex = this->searchQueue.readIndex + 1; + if (0x13a10 <= (int)this->searchQueue.readIndex) { + this->searchQueue.readIndex = 0; + } + if (this->searchQueue.readIndex == this->searchQueue.writeIndex) { + return FALSE; + } + } + } + return FALSE; + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/findOwnedGatehouse.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/findOwnedGatehouse.cpp new file mode 100644 index 0000000000..29004cd031 --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/findOwnedGatehouse.cpp @@ -0,0 +1,115 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/IO/LowLevelMemory.func.hpp" + +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_ClimbLogicDefinedData.hpp" +#include "OpenSHC/Globals/DAT_LowLevelMemory.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x004A19B0 + dword PathFindingState::findOwnedGatehouse(int playerID, uint x, uint y) + { + int (*paiVar3)[8]; + short _building; + byte _link; + dword _tile; + if (399 < x || 399 < y || DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[y * 400 + x] == '\0') { + return (dword)(0); + } + this->calculations = this->calculations + 1; + this->searchGeneration = this->searchGeneration + 1; + if (32000 < this->searchGeneration) { + this->searchGeneration = 1; + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 0x27420, '\0', (void*)((int)(DAT_TileMapState::instance.WalkLayer))); + } + this->searchQueue.readIndex = 0; + this->searchQueue.writeIndex = 1; + this->searchQueue.currentDistance = 1; + this->searchQueue.yQueue[0] = (short)y; + this->searchQueue.xQueue[0] = (short)x; + int _startTile = DAT_ViewportRenderState::instance.translationMatrix[y].addXgetTile + x; + this->searchQueue.tilesQueue[0] = _startTile; + DAT_TileMapState::instance.CertainPathLayer[_startTile] = 1; + DAT_TileMapState::instance.WalkLayer[this->searchQueue.tilesQueue[0]] = (short)this->searchGeneration; + while (this->searchQueue.readIndex != this->searchQueue.writeIndex) { + _tile = this->searchQueue.tilesQueue[this->searchQueue.readIndex]; + if ((int)_tile < 0) { + return (dword)(0); + } + if (0x13a10 <= (int)_tile) { + return (dword)(0); + } + int sVar1 = this->searchQueue.xQueue[this->searchQueue.readIndex]; + int sVar2 = this->searchQueue.yQueue[this->searchQueue.readIndex]; + this->searchQueue.currentDistance = (int)DAT_TileMapState::instance.CertainPathLayer[_tile]; + if (0x13a10 < (int)this->searchQueue.currentDistance) { + return (dword)(0); + } + _link = DAT_TileMapState::instance.PathLinkageLayer[_tile]; + int _direction = 0; + paiVar3 = DAT_TileMapState::instance.directionTranslationMatrix + sVar2; + do { + int _candidate = (*paiVar3)[0] + _tile; + if (DAT_TileMapState::instance.WalkLayer[_candidate] != this->searchGeneration + && (DAT_TileMapState::instance.LogicLayer[_candidate] & 0x30) == 0) { + if ((DAT_ClimbLogicDefinedData::instance.BitFlagHelperForPathLinkage[_direction] & _link) + == 0) { + _building = DAT_TileMapState::instance.BuildingLayer[_candidate]; + if (_building != 0 + && (int)(short)DAT_BuildingsState::instance.buildings[_building].buildingType - 45 < 2 + && DAT_BuildingsState::instance.buildings[_building].owner == playerID) { + /* + if gate house from player + */ + return (dword)(_tile); + } + } else { + /* + queue tiles + */ + DAT_TileMapState::instance.CertainPathLayer[_candidate] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[_candidate] = (short)this->searchGeneration; + this->searchQueue.xQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction] + .short_.xOffset + + sVar1; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction] + .short_.yOffset + + sVar2; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = _candidate; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + } + _direction = _direction + 1; + paiVar3 = (int (*)[8])(*paiVar3 + 1); + } while (_direction < 8); + this->searchQueue.readIndex = this->searchQueue.readIndex + 1; + if (0x13a10 <= (int)this->searchQueue.readIndex) { + this->searchQueue.readIndex = 0; + } + } + return (dword)(0); + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/findPathUsingClimbingWithHeightMargin16.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/findPathUsingClimbingWithHeightMargin16.cpp new file mode 100644 index 0000000000..7083962040 --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/findPathUsingClimbingWithHeightMargin16.cpp @@ -0,0 +1,205 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/IO/LowLevelMemory.func.hpp" +#include "OpenSHC/Map/Buildings/BuildingsState.func.hpp" +#include "OpenSHC/Map/Buildings/BuildingType.hpp" +#include "OpenSHC/Map/Buildings/BuildingTypeShort.hpp" +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_ClimbLogicDefinedData.hpp" +#include "OpenSHC/Globals/DAT_LowLevelMemory.hpp" +#include "OpenSHC/Globals/DAT_PathFindingState.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + + using OpenSHC::Map::Buildings::BuildingType; + using OpenSHC::Map::Buildings::BuildingTypeShort; + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x00498020 + BOOLEnum PathFindingState::findPathUsingClimbingWithHeightMargin16( + uint x, uint y, uint x2, uint y2, int budget, BOOLEnum continueSearch) + { + int (*paiVar4)[8]; + int _keepHeight; + int _tDiff; + int _direction; + uint _cHeight; + int _candidate; + BuildingTypeShort _cType; + uint _cLogic; + uint _tLogic; + BuildingTypeShort _tType; + uint _tile; + if (399 < x || 399 < y) { + return FALSE; + } + if (DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[y * 400 + x] == '\0') { + return FALSE; + } + if (x2 != 0xffffffff) { + if (399 < x2) { + return FALSE; + } + if (399 < y2) { + return FALSE; + } + if (DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[y2 * 400 + x2] == '\0') { + return FALSE; + } + } + if (continueSearch == FALSE) { + this->searchGeneration = this->searchGeneration + 1; + if (32000 < this->searchGeneration) { + this->searchGeneration = 1; + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 0x27420, '\0', (void*)((int)(DAT_TileMapState::instance.WalkLayer))); + } + this->searchQueue.writeIndex = 1; + this->searchQueue.readIndex = 0; + this->searchQueue.currentDistance = 1; + } + this->searchQueue.yQueue[0] = (short)y; + this->searchQueue.xQueue[0] = (short)x; + int _startTile = DAT_ViewportRenderState::instance.translationMatrix[y].addXgetTile + x; + this->searchQueue.tilesQueue[0] = _startTile; + DAT_TileMapState::instance.CertainPathLayer[_startTile] + = (short)this->searchQueue.currentDistance; + DAT_TileMapState::instance.WalkLayer[this->searchQueue.tilesQueue[0]] = (short)this->searchGeneration; + if (x2 == 0xffffffff) { + x = 0; + } else { + x = DAT_ViewportRenderState::instance.translationMatrix[y2].addXgetTile + x2; + } + while (this->searchQueue.readIndex != this->searchQueue.writeIndex) { + _tile = this->searchQueue.tilesQueue[this->searchQueue.readIndex]; + if (_tile == x) { + /* + if candidate matches target tile + */ + this->searchMatchCounter = this->searchMatchCounter + 1; + return TRUE; + } + if ((this->searchQueue.readIndex >= budget) || (0x13a10 <= _tile)) + break; + int sVar1 = (int)this->searchQueue.xQueue[this->searchQueue.readIndex]; + int sVar2 = (int)this->searchQueue.yQueue[this->searchQueue.readIndex]; + this->searchQueue.currentDistance = (int)DAT_TileMapState::instance.CertainPathLayer[_tile]; + if (0x78 < (int)this->searchQueue.currentDistance) + break; + uint _tHeight = (uint)DAT_TileMapState::instance.HeightLayer[_tile]; + _tLogic = DAT_TileMapState::instance.LogicLayer[_tile]; + paiVar4 = DAT_TileMapState::instance.directionTranslationMatrix + sVar2; + for (_direction = 0; _direction < 8; + _direction = _direction + 1, paiVar4 = (int (*)[8])(*paiVar4 + 1)) { + /* + for each direction, do: + */ + _candidate = (*paiVar4)[0] + _tile; + if (DAT_TileMapState::instance.WalkLayer[_candidate] != this->searchGeneration) { + if ((DAT_TileMapState::instance.PathLinkageLayer[_tile] + & DAT_ClimbLogicDefinedData::instance.BitFlagHelperForPathLinkage[_direction]) + == 0) { + /* + tile is not wall or gatehouse + */ + if ((_tLogic & 0x100) == 0) { + /* + tile is not moat + */ + _cLogic = DAT_TileMapState::instance.LogicLayer[_candidate]; + if (((_tLogic & 0x40000000) == 0 && (_cLogic & 0x40000000) != 0) + || ((_tLogic & 0x40000000) != 0 + && ((_cLogic & 0x40000800) != 0 || (_cLogic & 0x4a5015b1) == 0))) { + /* + candidate is moat or stairs OR not sea, border (edge), rocky, wall or + gatehouse, building, tree, rivere, crenel, farm field, moat + */ + _cHeight = (uint)DAT_TileMapState::instance.HeightLayer[_candidate]; + if ((_cLogic & 0x10000000) != 0) { + /* + candidate is keep + */ + _keepHeight = MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func:: + getBuildingHeightForBuildingID, + DAT_BuildingsState::ptr)( + (int)DAT_TileMapState::instance.BuildingLayer[_candidate]); + _cHeight = _cHeight + _keepHeight; + } + /* + test if height difference is within margin + */ + if ((int)_tHeight <= (int)(_cHeight + 16) && (int)_tHeight >= (int)(_cHeight - 16)) + goto LAB_00498308; + _cType = DAT_BuildingsState::instance + .buildings[DAT_TileMapState::instance.BuildingLayer[_candidate]] + .buildingType; + _tDiff = 0; + if ((_cType == OpenSHC::Map::Buildings::BT_GATEHOUSELARGE) + || (_cType == OpenSHC::Map::Buildings::BT_GATEHOUSESMALL)) { + _cHeight = _cHeight - 90; + } else { + _tType = DAT_BuildingsState::instance + .buildings[DAT_TileMapState::instance.BuildingLayer[_tile]] + .buildingType; + if ((_tType != OpenSHC::Map::Buildings::BT_GATEHOUSELARGE) + && (_tType != OpenSHC::Map::Buildings::BT_GATEHOUSESMALL)) + continue; + _tDiff = -90; + } + /* + test if height difference is within margin + */ + if ((int)(_tHeight + _tDiff) <= (int)(_cHeight + 0x10) + && (int)(_cHeight - 0x10) <= (int)(_tHeight + _tDiff)) + goto LAB_00498308; + } + } + } else { + LAB_00498308: + /* + add to queue also jumped to when height difference is within margin + */ + DAT_TileMapState::instance.CertainPathLayer[_candidate] + = (short)this->searchQueue.currentDistance + 1; + short sVar3 + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction] + .short_.xOffset; + DAT_TileMapState::instance.WalkLayer[_candidate] = (short)this->searchGeneration; + this->searchQueue.xQueue[this->searchQueue.writeIndex] = sVar3 + sVar1; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = _candidate; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction] + .short_.yOffset + + sVar2; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + } + } + this->searchQueue.readIndex = this->searchQueue.readIndex + 1; + if (0x13a10 <= (int)this->searchQueue.readIndex) { + this->searchQueue.readIndex = 0; + } + } + DAT_PathFindingState::instance.searchNonmatchCount = DAT_PathFindingState::instance.searchNonmatchCount + 1; + return FALSE; + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/findPathableTileWithoutUnitWithBuildingAtXY.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/findPathableTileWithoutUnitWithBuildingAtXY.cpp new file mode 100644 index 0000000000..cdaa63ee8b --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/findPathableTileWithoutUnitWithBuildingAtXY.cpp @@ -0,0 +1,135 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/IO/LowLevelMemory.func.hpp" +#include "OpenSHC/Map/Location/Point8ShortXY.hpp" + +#include "OpenSHC/Globals/DAT_LowLevelMemory.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + using OpenSHC::Map::Location::Point8ShortXY; + + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x0049CE40 + void PathFindingState::findPathableTileWithoutUnitWithBuildingAtXY(int unitID, int x, int y) + { + int (*paiVar3)[8]; + int _buildingAtStart; + int _tile; + int _x; + int _y; + this->calculations = this->calculations + 1; + this->ALG_ResultTile = 0; + this->ALG_ResultY = 0; + this->ALG_ResultX = 0; + if ((uint)x <= 399 && (uint)y <= 399 + && DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[y * 400 + x] != '\0') { + this->searchGeneration = this->searchGeneration + 1; + if (32000 < this->searchGeneration) { + this->searchGeneration = 1; + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 0x27420, '\0', (void*)((int)(DAT_TileMapState::instance.WalkLayer))); + } + this->searchQueue.readIndex = 0; + this->searchQueue.writeIndex = 1; + this->searchQueue.currentDistance = 1; + this->searchQueue.yQueue[0] = (short)y; + this->searchQueue.xQueue[0] = (short)x; + int _startTile = DAT_ViewportRenderState::instance.translationMatrix[y].addXgetTile + x; + this->searchQueue.tilesQueue[0] = _startTile; + DAT_TileMapState::instance.CertainPathLayer[_startTile] = (short)this->searchQueue.currentDistance; + DAT_TileMapState::instance.WalkLayer[this->searchQueue.tilesQueue[0]] = (short)this->searchGeneration; + _buildingAtStart = DAT_TileMapState::instance.BuildingLayer[this->searchQueue.tilesQueue[0]]; + if (this->searchQueue.readIndex != this->searchQueue.writeIndex) { + while (true) { + _tile = this->searchQueue.tilesQueue[this->searchQueue.readIndex]; + if (_tile < 0) { + break; + } + if (0x13a10 <= _tile) { + break; + } + _x = (int)this->searchQueue.xQueue[this->searchQueue.readIndex]; + _y = (int)this->searchQueue.yQueue[this->searchQueue.readIndex]; + int iVar2 = (int)_y; + int _unitID = (int)(short)DAT_TileMapState::instance.UnitLayer[_tile]; + if (_unitID == unitID) { + this->ALG_ResultX = (int)_x; + this->ALG_ResultY = iVar2; + this->ALG_ResultTile = _tile; + return; + } + /* + find building space without unit + */ + if (DAT_TileMapState::instance.OccupancyLayer[_tile] == '\0' && _unitID == 0 + && _buildingAtStart == DAT_TileMapState::instance.BuildingLayer[_tile]) { + this->ALG_ResultX = (int)_x; + this->ALG_ResultY = iVar2; + this->ALG_ResultTile = _tile; + return; + } + this->searchQueue.currentDistance = (int)DAT_TileMapState::instance.CertainPathLayer[_tile]; + if (0x13a10 < (int)this->searchQueue.currentDistance) { + return; + } + if (0x19 < (int)this->searchQueue.currentDistance) { + return; + } + for (int _direction = 0; _direction < 8; _direction = _direction + 2) { + /* + for each direction, do: + */ + int _candidate + = DAT_TileMapState::instance.directionTranslationMatrix[iVar2][_direction] + _tile; + if (DAT_TileMapState::instance.WalkLayer[_candidate] != this->searchGeneration + && (DAT_TileMapState::instance.LogicLayer[_candidate] & 0xb1U) == 0 + && (DAT_TileMapState::instance.LogicLayer[_candidate] & 0x1000U) == 0 + && (short)DAT_TileMapState::instance.PathConnectionLayer[_candidate] != 0) { + /* + queue pathable tiles that aren't see nor tree + */ + DAT_TileMapState::instance.CertainPathLayer[_candidate] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[_candidate] = (short)this->searchGeneration; + this->searchQueue.xQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction] + .short_.xOffset + + _x; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction] + .short_.yOffset + + _y; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = _candidate; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + } + + this->searchQueue.readIndex = this->searchQueue.readIndex + 1; + if (0x13a10 <= (int)this->searchQueue.readIndex) { + this->searchQueue.readIndex = 0; + } + if (this->searchQueue.readIndex == this->searchQueue.writeIndex) { + return; + } + } + } + } + return; + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/findPositionForGivenClimbArea.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/findPositionForGivenClimbArea.cpp new file mode 100644 index 0000000000..0df04d69b2 --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/findPositionForGivenClimbArea.cpp @@ -0,0 +1,48 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/Globals/DAT_ClimbLogicDefinedData.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x00497690 + void PathFindingState::findPositionForGivenClimbArea(int area, uint x, uint y) + { + if (x > 399 || y > 399) { + return; + } + if (DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[y * 400 + x] == '\0') { + return; + } + int _rowTile = DAT_ViewportRenderState::instance.translationMatrix[y].addXgetTile + x; + for (int _directionIndex = 0; _directionIndex < 8; _directionIndex = _directionIndex + 1) { + int _direction = (int)(char)DAT_ClimbLogicDefinedData::instance.DirectionArray[_directionIndex]; + if ((short)DAT_TileMapState::instance + .PathConnectionLayer[DAT_TileMapState::instance.directionTranslationMatrix[y][_direction] + + _rowTile] + == area) { + this->climbX + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction].int_.xOffset + + x; + this->climbY + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction].int_.yOffset + + y; + return; + } + } + return; + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/findSomeSuitableLocationUnk.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/findSomeSuitableLocationUnk.cpp new file mode 100644 index 0000000000..814c20ec81 --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/findSomeSuitableLocationUnk.cpp @@ -0,0 +1,182 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/IO/LowLevelMemory.func.hpp" +#include "OpenSHC/Map/Buildings/BuildingType.hpp" +#include "OpenSHC/Map/Buildings/BuildingTypeShort.hpp" +#include "OpenSHC/Map/Location/Point8ShortXY.hpp" + +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_GameState.hpp" +#include "OpenSHC/Globals/DAT_LowLevelMemory.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + + using OpenSHC::Map::Buildings::BuildingType; + using OpenSHC::Map::Buildings::BuildingTypeShort; + using OpenSHC::Map::Location::Point8ShortXY; + + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x004A1D30 + undefined4 PathFindingState::findSomeSuitableLocationUnk(int param_1, uint x, uint y, int param_4) + { + int iVar5; + if (399 < x || 399 < y) { + return (undefined4)(0); + } + if (DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[y * 400 + x] == '\0') { + return (undefined4)(0); + } + this->calculations = this->calculations + 1; + this->searchGeneration = this->searchGeneration + 1; + if (32000 < this->searchGeneration) { + this->searchGeneration = 1; + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 0x27420, '\0', (void*)((int)(DAT_TileMapState::instance.WalkLayer))); + } + this->searchQueue.readIndex = 0; + this->searchQueue.writeIndex = 1; + this->searchQueue.currentDistance = 1; + this->searchQueue.yQueue[0] = (short)y; + this->searchQueue.xQueue[0] = (short)x; + int _startTile = DAT_ViewportRenderState::instance.translationMatrix[y].addXgetTile + x; + this->searchQueue.tilesQueue[0] = _startTile; + DAT_TileMapState::instance.WalkLayer[this->searchQueue.tilesQueue[0]] = (short)this->searchGeneration; + DAT_TileMapState::instance.CertainPathLayer[_startTile] = (short)this->searchQueue.currentDistance; + if (this->searchQueue.readIndex != this->searchQueue.writeIndex) { + while ((iVar5 = this->searchQueue.tilesQueue[this->searchQueue.readIndex], + -1 < iVar5 && (iVar5 < 0x13a10))) { + int sVar1 = (int)this->searchQueue.xQueue[this->searchQueue.readIndex]; + int sVar2 = (int)this->searchQueue.yQueue[this->searchQueue.readIndex]; + this->searchQueue.currentDistance = (int)DAT_TileMapState::instance.CertainPathLayer[iVar5]; + if (0x13a10 < (int)this->searchQueue.currentDistance) { + return (undefined4)(0); + } + if ((int)this->searchQueue.currentDistance > param_4) { + return (undefined4)(0); + } + short sVar3 = DAT_TileMapState::instance.BuildingLayer[iVar5]; + if (sVar3 != 0) { + int BVar4 = (short)DAT_BuildingsState::instance.buildings[sVar3].buildingType; + if (BVar4 != OpenSHC::Map::Buildings::BT_QUARRY + && BVar4 != OpenSHC::Map::Buildings::BT_KILLINGPIT + && DAT_GameState::instance.mapAndTime + .playerTeams[DAT_BuildingsState::instance.buildings[sVar3].owner] + != DAT_GameState::instance.mapAndTime.playerTeams[param_1]) { + return (undefined4)(1); + } + } + if ((DAT_TileMapState::instance.LogicLayer[iVar5] & 0x100U) != 0 + && (DAT_TileMapState::instance.LogicLayer[iVar5] & 2U) == 0 + && DAT_GameState::instance.mapAndTime + .playerTeams[(DAT_TileMapState::instance.WallOwnerLayer[iVar5] & 7) + 1] + != DAT_GameState::instance.mapAndTime.playerTeams[param_1]) { + return (undefined4)(1); + } + for (int _direction = 0; _direction < 8; _direction = _direction + 4) { + int iVar8 = DAT_TileMapState::instance.directionTranslationMatrix[sVar2][_direction] + iVar5; + if (DAT_TileMapState::instance.WalkLayer[iVar8] != this->searchGeneration + && (DAT_TileMapState::instance.LogicLayer[iVar8] & 0x30) == 0) { + DAT_TileMapState::instance.CertainPathLayer[iVar8] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[iVar8] = (short)this->searchGeneration; + this->searchQueue.xQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction] + .short_.xOffset + + sVar1; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction] + .short_.yOffset + + sVar2; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = iVar8; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + iVar8 = DAT_TileMapState::instance.directionTranslationMatrix[sVar2][_direction + 1] + iVar5; + if (DAT_TileMapState::instance.WalkLayer[iVar8] != this->searchGeneration + && (DAT_TileMapState::instance.LogicLayer[iVar8] & 0x30) == 0) { + DAT_TileMapState::instance.CertainPathLayer[iVar8] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[iVar8] = (short)this->searchGeneration; + this->searchQueue.xQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction + 1] + .short_.xOffset + + sVar1; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction + 1] + .short_.yOffset + + sVar2; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = iVar8; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + iVar8 = DAT_TileMapState::instance.directionTranslationMatrix[sVar2][_direction + 2] + iVar5; + if (DAT_TileMapState::instance.WalkLayer[iVar8] != this->searchGeneration + && (DAT_TileMapState::instance.LogicLayer[iVar8] & 0x30) == 0) { + DAT_TileMapState::instance.CertainPathLayer[iVar8] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[iVar8] = (short)this->searchGeneration; + this->searchQueue.xQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction + 2] + .short_.xOffset + + sVar1; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction + 2] + .short_.yOffset + + sVar2; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = iVar8; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + iVar8 = DAT_TileMapState::instance.directionTranslationMatrix[sVar2][_direction + 3] + iVar5; + if (DAT_TileMapState::instance.WalkLayer[iVar8] != this->searchGeneration + && (DAT_TileMapState::instance.LogicLayer[iVar8] & 0x30) == 0) { + DAT_TileMapState::instance.CertainPathLayer[iVar8] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[iVar8] = (short)this->searchGeneration; + this->searchQueue.xQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction + 3] + .short_.xOffset + + sVar1; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction + 3] + .short_.yOffset + + sVar2; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = iVar8; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + } + + this->searchQueue.readIndex = this->searchQueue.readIndex + 1; + if (0x13a10 <= (int)this->searchQueue.readIndex) { + this->searchQueue.readIndex = 0; + } + if (this->searchQueue.readIndex == this->searchQueue.writeIndex) { + return (undefined4)(0); + } + } + } + return (undefined4)(0); + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/findSuitableSpawnLocationUnk.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/findSuitableSpawnLocationUnk.cpp new file mode 100644 index 0000000000..5a8740bd88 --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/findSuitableSpawnLocationUnk.cpp @@ -0,0 +1,98 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/IO/LowLevelMemory.func.hpp" +#include "OpenSHC/Map/Navigation/PathFindingState/LinkageNeighbourAsm.hpp" + +#include "OpenSHC/Globals/DAT_LowLevelMemory.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x00497B80 + undefined4 PathFindingState::findSuitableSpawnLocationUnk( + int x, int y, int x2, int y2, int param_5, int param_6) + { + if (399 < (uint)x || 399 < (uint)y) { + return (undefined4)(0); + } + if (DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[y * 400 + x] == '\0') { + return (undefined4)(0); + } + if (x2 != -1 + && (399 < (uint)x2 || 399 < (uint)y2 + || DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[y2 * 400 + x2] == '\0') + && 500 < param_5) { + param_5 = 500; + } + if (param_6 == 0) { + this->searchGeneration = this->searchGeneration + 1; + if (32000 < this->searchGeneration) { + this->searchGeneration = 1; + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 0x27420, '\0', (void*)((int)(DAT_TileMapState::instance.WalkLayer))); + } + this->searchQueue.writeIndex = 1; + this->searchQueue.readIndex = 0; + this->searchQueue.depth = 0; + } + /* + The eight-neighbour expansion below is handwritten assembly in the original and reaches + the layers and the queue through these locals; see LinkageNeighbourAsm.hpp. This is the + variant that only enters a neighbour whose OccupancyLayer byte is zero. + */ + short _curGen = (short)this->searchGeneration; + short* _walkLayer = DAT_TileMapState::instance.WalkLayer; + short* _certainPath = DAT_TileMapState::instance.CertainPathLayer; + uchar* _linkage = DAT_TileMapState::instance.PathLinkageLayer; + uchar* _occupancy = DAT_TileMapState::instance.OccupancyLayer; + int* _tilesQueue = this->searchQueue.tilesQueue; + short* _yQueue = this->searchQueue.yQueue; + int* _dirMatrix = &DAT_TileMapState::instance.directionTranslationMatrix[0][0]; + + this->searchQueue.yQueue[0] = (short)y; + this->searchQueue.tilesQueue[0] = DAT_ViewportRenderState::instance.translationMatrix[y].addXgetTile + x; + DAT_TileMapState::instance.CertainPathLayer[this->searchQueue.tilesQueue[0]] = 1; + DAT_TileMapState::instance.WalkLayer[this->searchQueue.tilesQueue[0]] = _curGen; + + y = this->searchQueue.writeIndex; + int _readIndex = this->searchQueue.readIndex; + param_6 = this->searchQueue.depth; + if (x2 == -1) { + x = 0; + } else { + x = DAT_ViewportRenderState::instance.translationMatrix[y2].addXgetTile + x2; + } + int _result = 0; + while (_readIndex != y && param_6 < param_5) { + param_6 = param_6 + 1; + int _tile = this->searchQueue.tilesQueue[_readIndex]; + if (_tile == x) { + _result = 1; + break; + } + int _cY = (ushort)this->searchQueue.yQueue[_readIndex]; + int _cCardinalDistance = _certainPath[_tile] + 1; + int _cLink = _linkage[_tile]; + + MACRO_LINKAGE_EXPAND_FREE_NEIGHBOURS(1, y) + + _readIndex = _readIndex + 1; + } + this->searchQueue.writeIndex = y; + this->searchQueue.readIndex = _readIndex; + this->searchQueue.depth = param_6; + return (undefined4)(_result); + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/findSupportPointIndex.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/findSupportPointIndex.cpp new file mode 100644 index 0000000000..c34dda9eb5 --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/findSupportPointIndex.cpp @@ -0,0 +1,116 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/IO/LowLevelMemory.func.hpp" +#include "OpenSHC/Map/Units/TroopValueState.func.hpp" + +#include "OpenSHC/Globals/DAT_ClimbLogicDefinedData.hpp" +#include "OpenSHC/Globals/DAT_LowLevelMemory.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_TribesState.hpp" +#include "OpenSHC/Globals/DAT_TroopValueState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x0049F2D0 + int PathFindingState::findSupportPointIndex(int max, uint x, uint y, int tribeID) + { + int iVar5; + int tile; + if (399 < x || 399 < y) { + return 0; + } + if (DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[y * 400 + x] == '\0') { + return 0; + } + this->calculations = this->calculations + 1; + this->searchGeneration = this->searchGeneration + 1; + if (32000 < this->searchGeneration) { + this->searchGeneration = 1; + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 0x27420, '\0', (void*)((int)(DAT_TileMapState::instance.WalkLayer))); + } + this->searchQueue.readIndex = 0; + this->searchQueue.writeIndex = 1; + this->searchQueue.currentDistance = 1; + this->searchQueue.yQueue[0] = (short)y; + this->searchQueue.xQueue[0] = (short)x; + int _startTile = DAT_ViewportRenderState::instance.translationMatrix[y].addXgetTile + x; + this->searchQueue.tilesQueue[0] = _startTile; + DAT_TileMapState::instance.CertainPathLayer[_startTile] = 1; + DAT_TileMapState::instance.WalkLayer[this->searchQueue.tilesQueue[0]] = (short)this->searchGeneration; + if (this->searchQueue.readIndex != this->searchQueue.writeIndex) { + while (true) { + int iVar4 = this->searchQueue.tilesQueue[this->searchQueue.readIndex]; + if (iVar4 < 0) { + break; + } + if (0x13a10 <= iVar4) { + break; + } + int sVar1 = (int)this->searchQueue.xQueue[this->searchQueue.readIndex]; + int sVar2 = (int)this->searchQueue.yQueue[this->searchQueue.readIndex]; + this->searchQueue.currentDistance = (int)DAT_TileMapState::instance.CertainPathLayer[iVar4]; + if (0x13a10 < (int)this->searchQueue.currentDistance) { + return 0; + } + if ((int)this->searchQueue.currentDistance > max) { + return 0; + } + for (int iVar6 = 0; iVar6 < 8; iVar6 = iVar6 + 1) { + if ((DAT_TileMapState::instance.PathLinkageLayer[iVar4] + & DAT_ClimbLogicDefinedData::instance.BitFlagHelperForPathLinkage[iVar6]) + != 0 + && (tile = DAT_TileMapState::instance.directionTranslationMatrix[sVar2][iVar6] + iVar4, + DAT_TileMapState::instance.WalkLayer[tile] != this->searchGeneration)) { + if (4 < (int)this->searchQueue.currentDistance + && (DAT_TileMapState::instance.AIInfoLayer[tile] & 0x40) != 0 + && (iVar5 + = MACRO_CALL_MEMBER(OpenSHC::Map::Units::TroopValueState_Func::getSupportPointIndex, + DAT_TroopValueState::ptr)(tile), + iVar5 != 0) + && iVar5 != DAT_TribesState::instance.tribes[tribeID].supportPointIndex + && DAT_TroopValueState::instance.attackInfo.supportPointsArray[iVar5].tribeID == 0) { + return iVar5; + } + DAT_TileMapState::instance.CertainPathLayer[tile] + = (short)this->searchQueue.currentDistance + 1; + int sVar3 = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[iVar6] + .short_.xOffset; + DAT_TileMapState::instance.WalkLayer[tile] = (short)this->searchGeneration; + this->searchQueue.xQueue[this->searchQueue.writeIndex] = sVar3 + sVar1; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[iVar6] + .short_.yOffset + + sVar2; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = tile; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + } + this->searchQueue.readIndex = this->searchQueue.readIndex + 1; + if (0x13a10 <= (int)this->searchQueue.readIndex) { + this->searchQueue.readIndex = 0; + } + if (this->searchQueue.readIndex == this->searchQueue.writeIndex) { + return 0; + } + } + } + return 0; + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/findUnitPreferredOrientationBasedConnectedTile.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/findUnitPreferredOrientationBasedConnectedTile.cpp new file mode 100644 index 0000000000..15e0ad721e --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/findUnitPreferredOrientationBasedConnectedTile.cpp @@ -0,0 +1,61 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/Map/Navigation/DirectionAlgorithmState.func.hpp" +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" +#include "OpenSHC/Map/Navigation/Algorithms/XYPair.hpp" + +#include "OpenSHC/Globals/DAT_ClimbLogicDefinedData.hpp" +#include "OpenSHC/Globals/DAT_DirectionAlgorithmState.hpp" +#include "OpenSHC/Globals/DAT_PathFindingState.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_UnitsState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + using OpenSHC::Map::Navigation::Algorithms::XYPair; + + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x004A8780 + int PathFindingState::findUnitPreferredOrientationBasedConnectedTile(int unitID, int tile) + { + int _can; + XYPair* pXVar1; + int _y; + int _candidate; + int _area; + _y = (int)DAT_ViewportRenderState::instance.tileTranslationMatrix_YComponent[tile]; + int _x = tile - DAT_ViewportRenderState::instance.translationMatrix[_y].addXgetTile; + MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::DirectionAlgorithmState_Func::calculatePreferredRelativeOrientation, + DAT_DirectionAlgorithmState::ptr)(_x, _y, (int)(DAT_UnitsState::instance.units[unitID].x), + (int)(DAT_UnitsState::instance.units[unitID].y)); + _area = (short)DAT_TileMapState::instance.PathConnectionLayer[DAT_UnitsState::instance.units[unitID].tile]; + pXVar1 + = DAT_ClimbLogicDefinedData::instance + .OrderedOrientationBasedCardinalDirectionList[DAT_DirectionAlgorithmState::instance.orientation]; + for (tile = 0; tile < 4; tile = tile + 1, pXVar1 = pXVar1 + 1) { + _candidate = DAT_ViewportRenderState::instance.translationMatrix[pXVar1->y + _y].addXgetTile + + ((XYPair*)&pXVar1->x)->x + _x; + int _toArea = (short)DAT_TileMapState::instance.PathConnectionLayer[_candidate]; + if (_area == _toArea + || (_can = MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func:: + calculateCanPlayerUnitsNavigateToAreaFromArea, + DAT_PathFindingState::ptr)( + (int)DAT_UnitsState::instance.units[unitID].owner, (dword)(_area), (dword)(_toArea), 0), + _can != 0)) { + return _candidate; + } + } + return 0; + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/findWalkableTileThatDoesNotContainUnit.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/findWalkableTileThatDoesNotContainUnit.cpp new file mode 100644 index 0000000000..422a1ab941 --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/findWalkableTileThatDoesNotContainUnit.cpp @@ -0,0 +1,130 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/IO/LowLevelMemory.func.hpp" +#include "OpenSHC/Map/TileMapState.func.hpp" +#include "OpenSHC/Map/Location/Point8ShortXY.hpp" + +#include "OpenSHC/Globals/DAT_LowLevelMemory.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_UnitsState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + using OpenSHC::Map::Location::Point8ShortXY; + + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x0049D340 + void PathFindingState::findWalkableTileThatDoesNotContainUnit(int unitID, uint x, uint y, int considerUnits) + { + uint _tHeight; + uint _absHeight; + int (*paiVar3)[8]; + int _area; + uint _heightDiff; + int _tile; + int _x; + int _y; + int _unitHeight = (short)DAT_UnitsState::instance.units[unitID].buildingHeight + + (short)DAT_UnitsState::instance.units[unitID].terrainOrClimbHeight; + this->calculations = this->calculations + 1; + this->ALG_ResultTile = 0; + this->ALG_ResultY = 0; + this->ALG_ResultX = 0; + if (x > 399 || y > 399) { + return; + } + if (DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[y * 400 + x] == '\0') { + return; + } + this->searchGeneration = this->searchGeneration + 1; + if (32000 < this->searchGeneration) { + this->searchGeneration = 1; + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 0x27420, '\0', (void*)((int)(DAT_TileMapState::instance.WalkLayer))); + } + this->searchQueue.currentDistance = 1; + this->searchQueue.writeIndex = 1; + this->searchQueue.readIndex = 0; + _area = (short)DAT_TileMapState::instance.PathConnectionLayer[DAT_UnitsState::instance.units[unitID].tile]; + this->searchQueue.yQueue[0] = (short)y; + this->searchQueue.xQueue[0] = (short)x; + int _startTile = DAT_ViewportRenderState::instance.translationMatrix[y].addXgetTile + x; + this->searchQueue.tilesQueue[0] = _startTile; + DAT_TileMapState::instance.CertainPathLayer[_startTile] = (short)this->searchQueue.currentDistance; + DAT_TileMapState::instance.WalkLayer[this->searchQueue.tilesQueue[0]] = (short)this->searchGeneration; + if ((DAT_TileMapState::instance.LogicLayer[this->searchQueue.tilesQueue[0]] & 0x30) == 0 + && this->searchQueue.readIndex != this->searchQueue.writeIndex) { + while (true) { + _tile = this->searchQueue.tilesQueue[this->searchQueue.readIndex]; + if (_tile < 0) { + break; + } + if (0x13a10 <= _tile) { + break; + } + _x = (int)this->searchQueue.xQueue[this->searchQueue.readIndex]; + _y = (int)this->searchQueue.yQueue[this->searchQueue.readIndex]; + int _unitAtTile = (short)DAT_TileMapState::instance.UnitLayer[_tile]; + if (((_unitAtTile == 0) || (considerUnits == 0)) && _unitAtTile != unitID + && _area == (short)DAT_TileMapState::instance.PathConnectionLayer[_tile] + && (_tHeight = MACRO_CALL_MEMBER( + OpenSHC::Map::TileMapState_Func::getTotalHeightAtTile, DAT_TileMapState::ptr)(_tile), + _heightDiff = _unitHeight - _tHeight, _absHeight = (int)_heightDiff >> 0x1f, + (int)((_heightDiff ^ _absHeight) - _absHeight) < 16)) { + this->ALG_ResultX = (int)_x; + this->ALG_ResultY = (int)_y; + this->ALG_ResultTile = _tile; + return; + } + this->searchQueue.currentDistance = (int)DAT_TileMapState::instance.CertainPathLayer[_tile]; + if (0x13a10 < (int)this->searchQueue.currentDistance) { + return; + } + for (int _direction = 0; _direction < 8; _direction = _direction + 2) { + int iVar1 = DAT_TileMapState::instance.directionTranslationMatrix[_y][_direction] + _tile; + if (DAT_TileMapState::instance.WalkLayer[iVar1] != this->searchGeneration + && (DAT_TileMapState::instance.LogicLayer[iVar1] & 0xb1U) == 0 + && (DAT_TileMapState::instance.LogicLayer[iVar1] & 0x1400U) == 0 + && (short)DAT_TileMapState::instance.PathConnectionLayer[iVar1] == _area) { + DAT_TileMapState::instance.CertainPathLayer[iVar1] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[iVar1] = (short)this->searchGeneration; + this->searchQueue.xQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction] + .short_.xOffset + + _x; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction] + .short_.yOffset + + _y; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = iVar1; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + } + + this->searchQueue.readIndex = this->searchQueue.readIndex + 1; + if (0x13a10 <= (int)this->searchQueue.readIndex) { + this->searchQueue.readIndex = 0; + } + if (this->searchQueue.readIndex == this->searchQueue.writeIndex) { + return; + } + } + } + return; + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/getGatehouseNearSomethingUnk.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/getGatehouseNearSomethingUnk.cpp new file mode 100644 index 0000000000..28a6e5e2cd --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/getGatehouseNearSomethingUnk.cpp @@ -0,0 +1,118 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/IO/LowLevelMemory.func.hpp" +#include "OpenSHC/Map/Buildings/BuildingLogicalState.hpp" +#include "OpenSHC/Map/Buildings/BuildingLogicalStateShort.hpp" +#include "OpenSHC/Map/Buildings/BuildingType.hpp" +#include "OpenSHC/Map/Buildings/BuildingTypeShort.hpp" + +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_ClimbLogicDefinedData.hpp" +#include "OpenSHC/Globals/DAT_GameState.hpp" +#include "OpenSHC/Globals/DAT_LowLevelMemory.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + + using OpenSHC::Map::Buildings::BuildingLogicalState; + using OpenSHC::Map::Buildings::BuildingLogicalStateShort; + using OpenSHC::Map::Buildings::BuildingType; + using OpenSHC::Map::Buildings::BuildingTypeShort; + + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x004A08E0 + int PathFindingState::getGatehouseNearSomethingUnk(int param_1, int param_2, int param_3, int maxDistance) + { + BuildingLogicalStateShort BVar2; + BuildingTypeShort BVar3; + int iVar4; + int (*paiVar8)[8]; + this->searchGeneration = this->searchGeneration + 1; + this->calculations = this->calculations + 1; + if (32000 < this->searchGeneration) { + this->searchGeneration = 1; + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 0x27420, '\0', (void*)((int)(DAT_TileMapState::instance.WalkLayer))); + } + this->searchQueue.yQueue[0] = (short)param_3; + this->searchQueue.readIndex = 0; + this->searchQueue.writeIndex = 1; + this->searchQueue.currentDistance = 1; + this->searchQueue.tilesQueue[0] + = DAT_ViewportRenderState::instance.translationMatrix[param_3].addXgetTile + param_2; + DAT_TileMapState::instance.WalkLayer[this->searchQueue.tilesQueue[0]] = (short)this->searchGeneration; + DAT_TileMapState::instance.CertainPathLayer[this->searchQueue.tilesQueue[0]] = 1; + if (this->searchQueue.readIndex != this->searchQueue.writeIndex) { + while ((iVar4 = this->searchQueue.tilesQueue[this->searchQueue.readIndex], + -1 < iVar4 && (iVar4 < 0x13a10))) { + int sVar1 = (int)this->searchQueue.yQueue[this->searchQueue.readIndex]; + this->searchQueue.currentDistance = (int)DAT_TileMapState::instance.CertainPathLayer[iVar4]; + if (0x13a10 < (int)this->searchQueue.currentDistance) { + return 0; + } + if ((int)this->searchQueue.currentDistance > maxDistance) { + return 0; + } + int iVar7 = 0; + paiVar8 = DAT_TileMapState::instance.directionTranslationMatrix + sVar1; + do { + int iVar6 = (*paiVar8)[0] + iVar4; + int iVar5 = (int)DAT_TileMapState::instance.BuildingLayer[iVar6]; + if (((iVar5 != 0) + || ((DAT_TileMapState::instance.PathLinkageLayer[iVar4] + & DAT_ClimbLogicDefinedData::instance.BitFlagHelperForPathLinkage[iVar7]) + != 0)) + && DAT_TileMapState::instance.WalkLayer[iVar6] != this->searchGeneration) { + DAT_TileMapState::instance.CertainPathLayer[iVar6] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[iVar6] = (short)this->searchGeneration; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[iVar7] + .short_.yOffset + + sVar1; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = iVar6; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + if (iVar5 != 0 + && DAT_GameState::instance.mapAndTime.playerTeams[param_1] + != DAT_GameState::instance.mapAndTime + .playerTeams[DAT_BuildingsState::instance.buildings[iVar5].owner] + && (BVar2 = DAT_BuildingsState::instance.buildings[iVar5].logicalState, + BVar2 != ((BuildingLogicalState)0) + && (BVar2 != OpenSHC::Map::Buildings::BLS_REMOVE)) + && (BVar3 = DAT_BuildingsState::instance.buildings[iVar5].buildingType, + BVar3 == OpenSHC::Map::Buildings::BT_GATEHOUSELARGE + || (BVar3 == OpenSHC::Map::Buildings::BT_GATEHOUSESMALL)) + && DAT_BuildingsState::instance.buildings[iVar5].fireDuration == 0) { + return iVar5; + } + } + iVar7 = iVar7 + 1; + paiVar8 = (int (*)[8])(*paiVar8 + 1); + } while (iVar7 < 8); + this->searchQueue.readIndex = this->searchQueue.readIndex + 1; + if (0x13a10 <= (int)this->searchQueue.readIndex) { + this->searchQueue.readIndex = 0; + } + if (this->searchQueue.readIndex == this->searchQueue.writeIndex) { + return 0; + } + } + } + return 0; + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/getTileInSquareBrush.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/getTileInSquareBrush.cpp new file mode 100644 index 0000000000..66ecce24ee --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/getTileInSquareBrush.cpp @@ -0,0 +1,107 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/IO/LowLevelMemory.func.hpp" + +#include "OpenSHC/Globals/DAT_LowLevelMemory.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + + /* + WARNING: Function: __alloca_probe replaced with injection: alloca_probe + */ + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + fixme:bug: the index parameter is off by -1 for brush indices larger than 6. Phrased differently, index 7 is + faulty decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x0049BE60 + void PathFindingState::getTileInSquareBrush(int brushTileIndex, uint x, uint y) + { + int (*_dirAtTile)[8]; + int _index_3; + int _tracker_3; + int _tracker; + uint _yArray[1000]; + int _tileArray[1000]; + int _tile_2; + uint _y; + int _yTranslationUnk; + /* + __chkstk + */ + _index_3 = 1; + this->calculations = this->calculations + 1; + this->searchGeneration = this->searchGeneration + 1; + _tracker = 0; + _tracker_3 = 0; + if (32000 < this->searchGeneration) { + this->searchGeneration = 1; + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 160800, '\0', (void*)((int)(DAT_TileMapState::instance.WalkLayer))); + } + this->resultTile = 0; + this->resultY = 0; + this->resultX = 0; + if (x <= 399 && y <= 399 + && DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[y * 400 + x] != '\0') { + _tileArray[0] = DAT_ViewportRenderState::instance.translationMatrix[y].addXgetTile + x; + _yArray[0] = y; + if (brushTileIndex <= 0) { + this->resultY = y; + this->resultTile = _tileArray[0]; + return; + } + while ((_tile_2 = _tileArray[_tracker_3], -1 < _tile_2 && (_tile_2 < 80400))) { + _y = _yArray[_tracker_3]; + if ((DAT_TileMapState::instance.LogicLayer[_tile_2] & 0x30) == 0) { + int _direction = 0; + _dirAtTile = DAT_TileMapState::instance.directionTranslationMatrix + _y; + do { + int _currentTile = (*_dirAtTile)[0] + _tile_2; + if (DAT_TileMapState::instance.WalkLayer[_currentTile] != this->searchGeneration) { + _tracker = _tracker + 1; + if (brushTileIndex <= _tracker) { + this->resultY = DAT_TerrainDefinedData::instance + .clockwiseCardinalTranslationMatrix[_direction] + .int_.yOffset + + _y; + this->resultTile = _currentTile; + return; + } + DAT_TileMapState::instance.WalkLayer[_currentTile] = (short)this->searchGeneration; + _yTranslationUnk + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction] + .int_.yOffset; + _tileArray[_index_3] = _currentTile; + _yArray[_index_3] = _yTranslationUnk + _y; + _index_3 = _index_3 + 1; + if (_index_3 >= 80400) { + _index_3 = 0; + } + } + _direction = _direction + 2; + _dirAtTile = (int (*)[8])(*_dirAtTile + 2); + } while (_direction < 8); + } + _tracker_3 = _tracker_3 + 1; + if (80400 < _tracker_3) { + _tracker_3 = 0; + } + if (_tracker_3 == _index_3) { + return; + } + } + } + return; + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/healUnitsOfPlayerWithinRadius.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/healUnitsOfPlayerWithinRadius.cpp new file mode 100644 index 0000000000..d736ed849b --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/healUnitsOfPlayerWithinRadius.cpp @@ -0,0 +1,177 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/IO/LowLevelMemory.func.hpp" +#include "OpenSHC/Map/Location/Point8ShortXY.hpp" + +#include "OpenSHC/Globals/DAT_LowLevelMemory.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_UnitsState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + using OpenSHC::Map::Location::Point8ShortXY; + + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + BFS from tile param_1 up to distance param_2. For every unit owned by player param_3 found on visited tiles, + adds param_4 health, clamped to the unit's maxHealth. Also updates healthPercentage and healthbar fields + accordingly. Used for area healing effects such as from buildings or abilities. renamed by: Claude + Sonnet 4.6 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x004A36B0 + undefined4 PathFindingState::healUnitsOfPlayerWithinRadius(int param_1, int param_2, int param_3, int param_4) + { + uint uVar4; + short sVar6; + int iVar8; + this->searchGeneration = this->searchGeneration + 1; + this->calculations = this->calculations + 1; + if (32000 < this->searchGeneration) { + this->searchGeneration = 1; + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 0x27420, '\0', (void*)((int)(DAT_TileMapState::instance.WalkLayer))); + } + this->searchQueue.yQueue[0] + = (short)DAT_ViewportRenderState::instance.tileTranslationMatrix_YComponent[param_1]; + this->searchQueue.tilesQueue[0] = param_1; + this->searchQueue.xQueue[0] = (short)param_1 + - (short)DAT_ViewportRenderState::instance.translationMatrix[this->searchQueue.yQueue[0]].addXgetTile; + this->searchQueue.readIndex = 0; + this->searchQueue.writeIndex = 1; + this->searchQueue.currentDistance = 1; + DAT_TileMapState::instance.CertainPathLayer[param_1] = 1; + DAT_TileMapState::instance.WalkLayer[this->searchQueue.tilesQueue[0]] = (short)this->searchGeneration; + if (this->searchQueue.readIndex != this->searchQueue.writeIndex) { + while (uVar4 = this->searchQueue.tilesQueue[this->searchQueue.readIndex], uVar4 <= 0x13a0f) { + int sVar1 = this->searchQueue.xQueue[this->searchQueue.readIndex]; + this->searchQueue.currentDistance = (int)DAT_TileMapState::instance.CertainPathLayer[uVar4]; + int sVar2 = this->searchQueue.yQueue[this->searchQueue.readIndex]; + if (0x13a10 < (int)this->searchQueue.currentDistance) { + return (undefined4)(0); + } + if ((int)this->searchQueue.currentDistance > param_2) { + return (undefined4)(0); + } + int uVar3 = (short)DAT_TileMapState::instance.UnitLayer[uVar4]; + while (iVar8 = (int)(short)uVar3, iVar8 != 0) { + if (DAT_UnitsState::instance.units[iVar8].owner == param_3) { + DAT_UnitsState::instance.units[iVar8].health + = DAT_UnitsState::instance.units[iVar8].health + param_4; + int iVar5 = DAT_UnitsState::instance.units[iVar8].maxHealth; + if (DAT_UnitsState::instance.units[iVar8].health > iVar5) { + DAT_UnitsState::instance.units[iVar8].health = iVar5; + } + if (iVar5 == 0) { + sVar6 = 100; + } else { + sVar6 = (short)((DAT_UnitsState::instance.units[iVar8].health * 100) / iVar5); + } + DAT_UnitsState::instance.units[iVar8].healthPercentage = sVar6; + DAT_UnitsState::instance.units[iVar8].healthbar + = sVar6 / 10; + } + uVar3 = DAT_UnitsState::instance.units[iVar8].nextUnitOnTheSameTile; + } + for (int _direction = 0; _direction < 8; _direction = _direction + 4) { + iVar8 = DAT_TileMapState::instance.directionTranslationMatrix[sVar2][_direction] + uVar4; + if (DAT_TileMapState::instance.WalkLayer[iVar8] != this->searchGeneration + && (DAT_TileMapState::instance.LogicLayer[iVar8] & 0x30) == 0) { + DAT_TileMapState::instance.CertainPathLayer[iVar8] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[iVar8] = (short)this->searchGeneration; + this->searchQueue.xQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction] + .short_.xOffset + + sVar1; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction] + .short_.yOffset + + sVar2; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = iVar8; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + iVar8 = DAT_TileMapState::instance.directionTranslationMatrix[sVar2][_direction + 1] + uVar4; + if (DAT_TileMapState::instance.WalkLayer[iVar8] != this->searchGeneration + && (DAT_TileMapState::instance.LogicLayer[iVar8] & 0x30) == 0) { + DAT_TileMapState::instance.CertainPathLayer[iVar8] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[iVar8] = (short)this->searchGeneration; + this->searchQueue.xQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction + 1] + .short_.xOffset + + sVar1; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction + 1] + .short_.yOffset + + sVar2; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = iVar8; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + iVar8 = DAT_TileMapState::instance.directionTranslationMatrix[sVar2][_direction + 2] + uVar4; + if (DAT_TileMapState::instance.WalkLayer[iVar8] != this->searchGeneration + && (DAT_TileMapState::instance.LogicLayer[iVar8] & 0x30) == 0) { + DAT_TileMapState::instance.CertainPathLayer[iVar8] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[iVar8] = (short)this->searchGeneration; + this->searchQueue.xQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction + 2] + .short_.xOffset + + sVar1; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction + 2] + .short_.yOffset + + sVar2; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = iVar8; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + iVar8 = DAT_TileMapState::instance.directionTranslationMatrix[sVar2][_direction + 3] + uVar4; + if (DAT_TileMapState::instance.WalkLayer[iVar8] != this->searchGeneration + && (DAT_TileMapState::instance.LogicLayer[iVar8] & 0x30) == 0) { + DAT_TileMapState::instance.CertainPathLayer[iVar8] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[iVar8] = (short)this->searchGeneration; + this->searchQueue.xQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction + 3] + .short_.xOffset + + sVar1; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction + 3] + .short_.yOffset + + sVar2; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = iVar8; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + } + + this->searchQueue.readIndex = this->searchQueue.readIndex + 1; + if (0x13a10 <= (int)this->searchQueue.readIndex) { + this->searchQueue.readIndex = 0; + } + if (this->searchQueue.readIndex == this->searchQueue.writeIndex) { + return (undefined4)(0); + } + } + } + return (undefined4)(0); + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/igniteFireAtTilesDistanceAway.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/igniteFireAtTilesDistanceAway.cpp new file mode 100644 index 0000000000..6bc5e205cf --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/igniteFireAtTilesDistanceAway.cpp @@ -0,0 +1,172 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/IO/LowLevelMemory.func.hpp" +#include "OpenSHC/Map/Entities.func.hpp" +#include "OpenSHC/Map/Location/Point8ShortXY.hpp" + +#include "OpenSHC/Globals/DAT_LowLevelMemory.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + using OpenSHC::Map::Location::Point8ShortXY; + + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x004A2DD0 + undefined4 PathFindingState::igniteFireAtTilesDistanceAway(int tile, int maxDistance, int playerID) + { + int iVar5; + uint _tiles[100]; + uint _tile; + this->calculations = this->calculations + 1; + int _index = 0; + this->searchGeneration = this->searchGeneration + 1; + if (32000 < this->searchGeneration) { + this->searchGeneration = 1; + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 0x27420, '\0', (void*)((int)(DAT_TileMapState::instance.WalkLayer))); + } + int _startY = (short)DAT_ViewportRenderState::instance.tileTranslationMatrix_YComponent[tile]; + this->searchQueue.yQueue[0] = (short)_startY; + this->searchQueue.xQueue[0] + = (short)tile - (short)DAT_ViewportRenderState::instance.translationMatrix[_startY].addXgetTile; + this->searchQueue.tilesQueue[0] = tile; + this->searchQueue.readIndex = 0; + this->searchQueue.writeIndex = 1; + this->searchQueue.currentDistance = 1; + DAT_TileMapState::instance.WalkLayer[this->searchQueue.tilesQueue[0]] = (short)this->searchGeneration; + DAT_TileMapState::instance.CertainPathLayer[tile] = 1; + if (this->searchQueue.readIndex != this->searchQueue.writeIndex) { + while (_tile = this->searchQueue.tilesQueue[this->searchQueue.readIndex], _tile <= 0x13a0f) { + int sVar1 = (int)this->searchQueue.xQueue[this->searchQueue.readIndex]; + int sVar2 = (int)this->searchQueue.yQueue[this->searchQueue.readIndex]; + this->searchQueue.currentDistance = (int)DAT_TileMapState::instance.CertainPathLayer[_tile]; + if (0x13a10 < (int)this->searchQueue.currentDistance + || (int)this->searchQueue.currentDistance > maxDistance) + break; + _tiles[_index] = _tile; + _index = _index + 1; + for (int _direction = 0; _direction < 8; _direction = _direction + 4) { + /* + For every direction, queue tiles that are not a border tile + */ + iVar5 = DAT_TileMapState::instance.directionTranslationMatrix[sVar2][_direction] + _tile; + if (DAT_TileMapState::instance.WalkLayer[iVar5] != this->searchGeneration + && (DAT_TileMapState::instance.LogicLayer[iVar5] & 0x30) == 0) { + DAT_TileMapState::instance.CertainPathLayer[iVar5] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[iVar5] = (short)this->searchGeneration; + this->searchQueue.xQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction] + .short_.xOffset + + sVar1; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction] + .short_.yOffset + + sVar2; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = iVar5; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + iVar5 = DAT_TileMapState::instance.directionTranslationMatrix[sVar2][_direction + 1] + _tile; + if (DAT_TileMapState::instance.WalkLayer[iVar5] != this->searchGeneration + && (DAT_TileMapState::instance.LogicLayer[iVar5] & 0x30) == 0) { + DAT_TileMapState::instance.CertainPathLayer[iVar5] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[iVar5] = (short)this->searchGeneration; + this->searchQueue.xQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction + 1] + .short_.xOffset + + sVar1; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction + 1] + .short_.yOffset + + sVar2; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = iVar5; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + iVar5 = DAT_TileMapState::instance.directionTranslationMatrix[sVar2][_direction + 2] + _tile; + if (DAT_TileMapState::instance.WalkLayer[iVar5] != this->searchGeneration + && (DAT_TileMapState::instance.LogicLayer[iVar5] & 0x30) == 0) { + DAT_TileMapState::instance.CertainPathLayer[iVar5] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[iVar5] = (short)this->searchGeneration; + this->searchQueue.xQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction + 2] + .short_.xOffset + + sVar1; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction + 2] + .short_.yOffset + + sVar2; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = iVar5; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + iVar5 = DAT_TileMapState::instance.directionTranslationMatrix[sVar2][_direction + 3] + _tile; + if (DAT_TileMapState::instance.WalkLayer[iVar5] != this->searchGeneration + && (DAT_TileMapState::instance.LogicLayer[iVar5] & 0x30) == 0) { + DAT_TileMapState::instance.CertainPathLayer[iVar5] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[iVar5] = (short)this->searchGeneration; + this->searchQueue.xQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction + 3] + .short_.xOffset + + sVar1; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction + 3] + .short_.yOffset + + sVar2; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = iVar5; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + } + + this->searchQueue.readIndex = this->searchQueue.readIndex + 1; + if (0x13a10 <= (int)this->searchQueue.readIndex) { + this->searchQueue.readIndex = 0; + } + if (this->searchQueue.readIndex == this->searchQueue.writeIndex) + break; + } + } + int _index2 = 0; + if (0 < _index) { + do { + uint _cTile = _tiles[_index2]; + MACRO_CALL(OpenSHC::Map::Entities_Func::IgniteFireAtMiniTile_Convenience)(playerID, + (_cTile + - DAT_ViewportRenderState::instance + .translationMatrix[DAT_ViewportRenderState::instance + .tileTranslationMatrix_YComponent[_cTile]] + .addXgetTile) + * 8, + (int)((short)DAT_ViewportRenderState::instance.tileTranslationMatrix_YComponent[_cTile] * 8), + (int)(DAT_TileMapState::instance.HeightLayer[_cTile]), 2); + _index2 = _index2 + 1; + } while (_index2 < _index); + } + return (undefined4)(0); + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/isEnemyTooCloseUnk.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/isEnemyTooCloseUnk.cpp new file mode 100644 index 0000000000..78dfb7f648 --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/isEnemyTooCloseUnk.cpp @@ -0,0 +1,62 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +#include "OpenSHC/Globals/DAT_GameState.hpp" +#include "OpenSHC/Globals/DAT_UnitsState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + /* + decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x004A15B0 + BOOLEnum PathFindingState::isEnemyTooCloseUnk(int playerID, uint x, uint y, int requiredDistance) + { + short* _enemyIdPtr; + int _xEnemyDistance; + int _enemyLoopCounter; + int _yEnemyDistance; + int _enemies; + int _enemyID; + if (399 < x || 399 < y) { + return FALSE; + } + if (DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[y * 400 + x] == '\0') { + return FALSE; + } + int _requiredDistanceSquared = requiredDistance * requiredDistance; + int* _pEnemyUid = DAT_GameState::instance.mapAndTime.playerEnemenyUnitUIDShortList[playerID]; + _enemies = DAT_GameState::instance.playerDataArray[playerID].enemies; + _enemyLoopCounter = 0; + if (0 < _enemies) { + _enemyIdPtr = DAT_GameState::instance.playerDataArray[playerID].enemyIDArray; + do { + _enemyID = *_enemyIdPtr; + if (DAT_UnitsState::instance.units[_enemyID].dying == 0 + && DAT_UnitsState::instance.units[_enemyID].uid == _pEnemyUid[_enemyLoopCounter] + && (_xEnemyDistance = x - (int)DAT_UnitsState::instance.units[_enemyID].x, + _yEnemyDistance = y - (int)DAT_UnitsState::instance.units[_enemyID].y, + _yEnemyDistance * _yEnemyDistance + _xEnemyDistance * _xEnemyDistance + < _requiredDistanceSquared + && ((DAT_UnitsState::instance.units[_enemyID].unknownTestAgainst0_2 == 0 + && (DAT_UnitsState::instance.units[_enemyID].moveRelatedFlag != 1)))) + && DAT_UnitsState::instance.units[_enemyID].isStalked == 0 + && DAT_UnitsState::instance.units[_enemyID].owner != 0) { + return TRUE; + } + _enemyLoopCounter = _enemyLoopCounter + 1; + _enemyIdPtr = _enemyIdPtr + 1; + } while (_enemyLoopCounter < _enemies); + } + return FALSE; + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/isOpponentBuildingInRange.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/isOpponentBuildingInRange.cpp new file mode 100644 index 0000000000..15dba819c2 --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/isOpponentBuildingInRange.cpp @@ -0,0 +1,133 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/IO/LowLevelMemory.func.hpp" +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" +#include "OpenSHC/Map/Location/Point8ShortXY.hpp" + +#include "OpenSHC/Globals/DAT_BuildingDefinedData.hpp" +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_GameState.hpp" +#include "OpenSHC/Globals/DAT_LowLevelMemory.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + using OpenSHC::Map::Location::Point8ShortXY; + + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x004A9200 + undefined4 PathFindingState::isOpponentBuildingInRange( + int playerID, int x, int y, int range, int param_5, int param_6, int keepRange) + { + int iVar1; + int (*paiVar3)[8]; + int _tile; + short _buildingID; + int _x; + int _y; + if (399 < (uint)x || 399 < (uint)y) { + return (undefined4)(0); + } + if (DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[y * 400 + x] == '\0') { + return (undefined4)(0); + } + this->calculations = this->calculations + 1; + this->searchGeneration = this->searchGeneration + 1; + if (32000 < this->searchGeneration) { + this->searchGeneration = 1; + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 0x27420, '\0', (void*)((int)(DAT_TileMapState::instance.WalkLayer))); + } + this->searchQueue.readIndex = 0; + this->searchQueue.writeIndex = 1; + this->searchQueue.currentDistance = 1; + this->searchQueue.yQueue[0] = (short)y; + this->searchQueue.xQueue[0] = (short)x; + int _startTile = DAT_ViewportRenderState::instance.translationMatrix[y].addXgetTile + x; + this->searchQueue.tilesQueue[0] = _startTile; + DAT_TileMapState::instance.CertainPathLayer[_startTile] = (short)this->searchQueue.currentDistance; + DAT_TileMapState::instance.WalkLayer[this->searchQueue.tilesQueue[0]] = (short)this->searchGeneration; + if (this->searchQueue.readIndex != this->searchQueue.writeIndex) { + while (true) { + _tile = this->searchQueue.tilesQueue[this->searchQueue.readIndex]; + if (_tile < 0) { + break; + } + if (80400 <= _tile) { + break; + } + this->searchQueue.currentDistance = (int)DAT_TileMapState::instance.CertainPathLayer[_tile]; + _x = (int)this->searchQueue.xQueue[this->searchQueue.readIndex]; + _y = (int)this->searchQueue.yQueue[this->searchQueue.readIndex]; + if (80400 < (int)this->searchQueue.currentDistance + || (int)this->searchQueue.currentDistance > range) + break; + _buildingID = DAT_TileMapState::instance.BuildingLayer[_tile]; + if (_buildingID != 0 + && DAT_BuildingDefinedData::instance.BuildingTypeOwnable + [(short)DAT_BuildingsState::instance.buildings[_buildingID].buildingType] + != 0 + && DAT_GameState::instance.mapAndTime + .playerTeams[DAT_BuildingsState::instance.buildings[_buildingID].owner] + != DAT_GameState::instance.mapAndTime.playerTeams[playerID]) { + return (undefined4)(1); + } + if ((DAT_TileMapState::instance.LogicLayer[_tile] & 0x100U) != 0 + && (DAT_TileMapState::instance.LogicLayer[_tile] & 2U) == 0 + && DAT_GameState::instance.mapAndTime + .playerTeams[(DAT_TileMapState::instance.WallOwnerLayer[_tile] & 7) + 1] + != DAT_GameState::instance.mapAndTime.playerTeams[playerID]) { + return (undefined4)(1); + } + for (int _direction = 0; _direction < 8; _direction = _direction + 2) { + int _newTile = DAT_TileMapState::instance.directionTranslationMatrix[_y][_direction] + _tile; + if (DAT_TileMapState::instance.WalkLayer[_newTile] != this->searchGeneration + && (DAT_TileMapState::instance.LogicLayer[_newTile] & 0x30) == 0) { + DAT_TileMapState::instance.CertainPathLayer[_newTile] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[_newTile] = (short)this->searchGeneration; + this->searchQueue.xQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction] + .short_.xOffset + + _x; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction] + .short_.yOffset + + _y; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = _newTile; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (80400 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + } + + this->searchQueue.readIndex = this->searchQueue.readIndex + 1; + if (80400 <= (int)this->searchQueue.readIndex) { + this->searchQueue.readIndex = 0; + } + if (this->searchQueue.readIndex == this->searchQueue.writeIndex) + break; + } + } + if (keepRange != -1) { + iVar1 = MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::isTileInRangeOfKeepRange, + this)(playerID, (uint)(x), (uint)(y), keepRange); + if (iVar1 != 0) { + return (undefined4)(1); + } + } + return (undefined4)(0); + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/isSignPostWithinDistance.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/isSignPostWithinDistance.cpp new file mode 100644 index 0000000000..4025fac425 --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/isSignPostWithinDistance.cpp @@ -0,0 +1,180 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/IO/LowLevelMemory.func.hpp" +#include "OpenSHC/Game/GameMode.hpp" +#include "OpenSHC/Map/Buildings/BuildingType.hpp" +#include "OpenSHC/Map/Location/Point8ShortXY.hpp" +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_GameSynchronyState.hpp" +#include "OpenSHC/Globals/DAT_LowLevelMemory.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + + using OpenSHC::Game::GameMode; + using OpenSHC::Map::Buildings::BuildingType; + using OpenSHC::Map::Location::Point8ShortXY; + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + /* + WARNING: Enum "DPSEND_EnumInt": Some values do not have unique names + */ + /* + WARNING: Enum "DPERRInt": Some values do not have unique names + */ + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x004A2650 + BOOLEnum PathFindingState::isSignPostWithinDistance(uint x, uint y, int limit) + { + int iVar3; + if (DAT_GameSynchronyState::instance.currentGameMode != OpenSHC::Game::GM_SOLITARY) { + return FALSE; + } + if (399 < x || 399 < y) { + return FALSE; + } + if (DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[y * 400 + x] == '\0') { + return FALSE; + } + this->calculations = this->calculations + 1; + this->searchGeneration = this->searchGeneration + 1; + if (32000 < this->searchGeneration) { + this->searchGeneration = 1; + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 0x27420, '\0', (void*)((int)(DAT_TileMapState::instance.WalkLayer))); + } + this->searchQueue.readIndex = 0; + this->searchQueue.writeIndex = 1; + this->searchQueue.currentDistance = 1; + this->searchQueue.yQueue[0] = (short)y; + this->searchQueue.xQueue[0] = (short)x; + this->searchQueue.tilesQueue[0] = DAT_ViewportRenderState::instance.translationMatrix[y].addXgetTile + x; + DAT_TileMapState::instance.WalkLayer[this->searchQueue.tilesQueue[0]] = (short)this->searchGeneration; + DAT_TileMapState::instance.CertainPathLayer[this->searchQueue.tilesQueue[0]] = 1; + if (this->searchQueue.readIndex != this->searchQueue.writeIndex) { + while ((iVar3 = this->searchQueue.tilesQueue[this->searchQueue.readIndex], + -1 < iVar3 && (iVar3 < 0x13a10))) { + int sVar1 = (int)this->searchQueue.xQueue[this->searchQueue.readIndex]; + int sVar2 = (int)this->searchQueue.yQueue[this->searchQueue.readIndex]; + this->searchQueue.currentDistance = (int)DAT_TileMapState::instance.CertainPathLayer[iVar3]; + if (0x13a10 < (int)this->searchQueue.currentDistance) { + return FALSE; + } + if ((int)this->searchQueue.currentDistance > limit) { + return FALSE; + } + int _building = DAT_TileMapState::instance.BuildingLayer[iVar3]; + if ((_building != 0) + && (DAT_BuildingsState::instance.buildings[_building].buildingType + == OpenSHC::Map::Buildings::BT_SIGNPOST)) { + return TRUE; + } + for (int _direction = 0; _direction < 8; _direction = _direction + 4) { + int iVar6 = DAT_TileMapState::instance.directionTranslationMatrix[sVar2][_direction] + iVar3; + if (DAT_TileMapState::instance.WalkLayer[iVar6] != this->searchGeneration + && (DAT_TileMapState::instance.LogicLayer[iVar6] & 0x30) == 0) { + DAT_TileMapState::instance.CertainPathLayer[iVar6] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[iVar6] = (short)this->searchGeneration; + this->searchQueue.xQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction] + .short_.xOffset + + sVar1; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction] + .short_.yOffset + + sVar2; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = iVar6; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + iVar6 = DAT_TileMapState::instance.directionTranslationMatrix[sVar2][_direction + 1] + iVar3; + if (DAT_TileMapState::instance.WalkLayer[iVar6] != this->searchGeneration + && (DAT_TileMapState::instance.LogicLayer[iVar6] & 0x30) == 0) { + DAT_TileMapState::instance.CertainPathLayer[iVar6] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[iVar6] = (short)this->searchGeneration; + this->searchQueue.xQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction + 1] + .short_.xOffset + + sVar1; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction + 1] + .short_.yOffset + + sVar2; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = iVar6; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + iVar6 = DAT_TileMapState::instance.directionTranslationMatrix[sVar2][_direction + 2] + iVar3; + if (DAT_TileMapState::instance.WalkLayer[iVar6] != this->searchGeneration + && (DAT_TileMapState::instance.LogicLayer[iVar6] & 0x30) == 0) { + DAT_TileMapState::instance.CertainPathLayer[iVar6] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[iVar6] = (short)this->searchGeneration; + this->searchQueue.xQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction + 2] + .short_.xOffset + + sVar1; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction + 2] + .short_.yOffset + + sVar2; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = iVar6; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + iVar6 = DAT_TileMapState::instance.directionTranslationMatrix[sVar2][_direction + 3] + iVar3; + if (DAT_TileMapState::instance.WalkLayer[iVar6] != this->searchGeneration + && (DAT_TileMapState::instance.LogicLayer[iVar6] & 0x30) == 0) { + DAT_TileMapState::instance.CertainPathLayer[iVar6] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[iVar6] = (short)this->searchGeneration; + this->searchQueue.xQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction + 3] + .short_.xOffset + + sVar1; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction + 3] + .short_.yOffset + + sVar2; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = iVar6; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + } + + this->searchQueue.readIndex = this->searchQueue.readIndex + 1; + if (0x13a10 <= (int)this->searchQueue.readIndex) { + this->searchQueue.readIndex = 0; + } + if (this->searchQueue.readIndex == this->searchQueue.writeIndex) { + return FALSE; + } + } + } + return FALSE; + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/isTileInRangeOfKeepRange.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/isTileInRangeOfKeepRange.cpp new file mode 100644 index 0000000000..b28c1b6261 --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/isTileInRangeOfKeepRange.cpp @@ -0,0 +1,65 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/Map/Navigation/DirectionAlgorithmState.func.hpp" +#include "OpenSHC/Game/Player/BuildingEntryInfo.hpp" +#include "OpenSHC/Map/Buildings/BuildingFailReasonEnum.hpp" + +#include "OpenSHC/Globals/DAT_DirectionAlgorithmState.hpp" +#include "OpenSHC/Globals/DAT_GameState.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + + using OpenSHC::Game::Player::BuildingEntryInfo; + using OpenSHC::Map::Buildings::BuildingFailReasonEnum; + + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x004A1C40 + undefined4 PathFindingState::isTileInRangeOfKeepRange(int playerID, uint x, uint y, int range) + { + int* piVar1; + int* piVar2; + if (x > 399 || y > 399) { + return (undefined4)(0); + } + if (DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[y * 400 + x] == '\0') { + return (undefined4)(0); + } + if (DAT_GameState::instance.playerDataArray[playerID].keep.id != 0 + && (MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::DirectionAlgorithmState_Func::setAxisBasedDistanceResult, + DAT_DirectionAlgorithmState::ptr)(x, (int)(y), + DAT_GameState::instance.playerDataArray[playerID].keep.xEntry, + DAT_GameState::instance.playerDataArray[playerID].keep.yEntry), + DAT_DirectionAlgorithmState::instance.distanceHigh <= range)) { + return (undefined4)(0); + } + piVar1 = &DAT_GameState::instance.playerDataArray[1].keep.tileEntry; + piVar2 = DAT_GameState::instance.mapAndTime.playerTeams + 1; + while (*piVar2 != DAT_GameState::instance.mapAndTime.playerTeams[playerID] + || ((BuildingEntryInfo*)(piVar1 + -3))->id == 0 + || (MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::DirectionAlgorithmState_Func::setAxisBasedDistanceResult, + DAT_DirectionAlgorithmState::ptr)(x, (int)(y), (int)(piVar1[-2]), (int)(piVar1[-1])), + DAT_DirectionAlgorithmState::instance.distanceHigh > range / 2)) { + piVar2 = piVar2 + 1; + piVar1 = piVar1 + 0xe7d; + if ((int)&DAT_GameState::instance.mapAndTime.playerTeams[9] <= (int)piVar2) { + DAT_TileMapState::instance.buildingPlacementFailReason = ((BuildingFailReasonEnum)0x12); + return (undefined4)(1); + } + } + return (undefined4)(0); + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/isUsableClimbWithinArea.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/isUsableClimbWithinArea.cpp new file mode 100644 index 0000000000..7e2ff91afd --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/isUsableClimbWithinArea.cpp @@ -0,0 +1,29 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + /* + decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x004A4B30 + BOOLEnum PathFindingState::isUsableClimbWithinArea(int area, int wallDataID) + { + if ((this->climbData[wallDataID].canBeUsed == 1) + && (this->climbData[wallDataID].isRecognizedByPathfinding != 0)) { + if (this->climbData[wallDataID].area == area) { + return TRUE; + } + return (uint)(this->climbData[wallDataID].wallGroupAreaID == area); + } + return FALSE; + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/pathFindingDeerAndLionsUnk.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/pathFindingDeerAndLionsUnk.cpp new file mode 100644 index 0000000000..a0e58f3564 --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/pathFindingDeerAndLionsUnk.cpp @@ -0,0 +1,180 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/IO/LowLevelMemory.func.hpp" +#include "OpenSHC/Map/Location/Point8IntXY.hpp" + +#include "OpenSHC/Globals/DAT_LowLevelMemory.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + using OpenSHC::Map::Location::Point8IntXY; + + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + Computes the distance to reach x and y, has a shortcut to basically return distance 1 if the area of the + destination is the same as the current area was decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x0049B1D0 + void PathFindingState::pathFindingDeerAndLionsUnk(int originArea, uint destinationX, uint destinationY) + { + int _neswTile1; + int _neswTile2; + int _neswTile3; + int _neswTile4; + int _currentTile; + if (destinationX <= 399 && destinationY <= 399 + && DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[destinationY * 400 + destinationX] + != '\0') { + this->calculations = this->calculations + 1; + this->searchGeneration = this->searchGeneration + 1; + this->climbX = destinationX; + this->climbY = destinationY; + if (32000 < this->searchGeneration) { + this->searchGeneration = 1; + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 0x27420, '\0', (void*)((int)(DAT_TileMapState::instance.WalkLayer))); + } + this->searchQueue.readIndex = 0; + this->searchQueue.writeIndex = 1; + this->searchQueue.xQueue[0] = (short)destinationX; + this->searchQueue.currentDistance = 1; + this->searchQueue.yQueue[0] = (short)destinationY; + this->searchQueue.tilesQueue[0] + = destinationX + DAT_ViewportRenderState::instance.translationMatrix[destinationY].addXgetTile; + DAT_TileMapState::instance.WalkLayer[this->searchQueue.tilesQueue[0]] = (short)this->searchGeneration; + DAT_TileMapState::instance.CertainPathLayer[this->searchQueue.tilesQueue[0]] = 1; + if (this->searchQueue.readIndex != this->searchQueue.writeIndex) { + while ((_currentTile = this->searchQueue.tilesQueue[this->searchQueue.readIndex], + -1 < _currentTile && (_currentTile < 80400))) { + int _currentX = (int)this->searchQueue.xQueue[this->searchQueue.readIndex]; + int _currentY = (int)this->searchQueue.yQueue[this->searchQueue.readIndex]; + if ((short)DAT_TileMapState::instance.PathConnectionLayer[_currentTile] == originArea) { + this->climbX = (int)_currentX; + this->climbY = (int)_currentY; + return; + } + this->searchQueue.currentDistance + = (int)DAT_TileMapState::instance.CertainPathLayer[_currentTile]; + if (6 < (int)this->searchQueue.currentDistance) { + return; + } + for (int _direction = 0; _direction < 8; _direction = _direction + 4) { + _neswTile1 + = DAT_TileMapState::instance.directionTranslationMatrix[_currentY][_direction + 0] + + _currentTile; + if ((DAT_TileMapState::instance.LogicLayer[_neswTile1] & 0x30) == 0) { + DAT_TileMapState::instance.CertainPathLayer[_neswTile1] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[_neswTile1] = (short)this->searchGeneration; + this->searchQueue.xQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance + .clockwiseCardinalTranslationMatrix[_direction + 0] + .int_.xOffset + + _currentX; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance + .clockwiseCardinalTranslationMatrix[_direction + 0] + .int_.yOffset + + _currentY; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = _neswTile1; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + _neswTile2 + = DAT_TileMapState::instance.directionTranslationMatrix[_currentY][_direction + 1] + + _currentTile; + if ((DAT_TileMapState::instance.LogicLayer[_neswTile2] & 0x30) == 0) { + DAT_TileMapState::instance.CertainPathLayer[_neswTile2] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[_neswTile2] = (short)this->searchGeneration; + this->searchQueue.xQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance + .clockwiseCardinalTranslationMatrix[_direction + 1] + .int_.xOffset + + _currentX; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance + .clockwiseCardinalTranslationMatrix[_direction + 1] + .int_.yOffset + + _currentY; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = _neswTile2; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + _neswTile3 + = DAT_TileMapState::instance.directionTranslationMatrix[_currentY][_direction + 2] + + _currentTile; + if ((DAT_TileMapState::instance.LogicLayer[_neswTile3] & 0x30) == 0) { + DAT_TileMapState::instance.CertainPathLayer[_neswTile3] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[_neswTile3] = (short)this->searchGeneration; + this->searchQueue.xQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance + .clockwiseCardinalTranslationMatrix[_direction + 2] + .int_.xOffset + + _currentX; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance + .clockwiseCardinalTranslationMatrix[_direction + 2] + .int_.yOffset + + _currentY; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = _neswTile3; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + _neswTile4 + = DAT_TileMapState::instance.directionTranslationMatrix[_currentY][_direction + 3] + + _currentTile; + if ((DAT_TileMapState::instance.LogicLayer[_neswTile4] & 0x30) == 0) { + DAT_TileMapState::instance.CertainPathLayer[_neswTile4] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[_neswTile4] = (short)this->searchGeneration; + this->searchQueue.xQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance + .clockwiseCardinalTranslationMatrix[_direction + 3] + .int_.xOffset + + _currentX; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance + .clockwiseCardinalTranslationMatrix[_direction + 3] + .int_.yOffset + + _currentY; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = _neswTile4; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + } + this->searchQueue.readIndex = this->searchQueue.readIndex + 1; + if (80400 <= (int)this->searchQueue.readIndex) { + this->searchQueue.readIndex = 0; + } + /* + the right hand side stops incrementing if no valid tiles are found, so the left hand side + catches up breaking when finished. Very elegant + */ + if (this->searchQueue.readIndex == this->searchQueue.writeIndex) { + return; + } + } + } + } + return; + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/pathFindingRelated.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/pathFindingRelated.cpp new file mode 100644 index 0000000000..9961636a0a --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/pathFindingRelated.cpp @@ -0,0 +1,139 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/IO/LowLevelMemory.func.hpp" +#include "OpenSHC/Map/Navigation/DirectionAlgorithmState.func.hpp" + +#include "OpenSHC/Globals/DAT_ClimbLogicDefinedData.hpp" +#include "OpenSHC/Globals/DAT_DirectionAlgorithmState.hpp" +#include "OpenSHC/Globals/DAT_LowLevelMemory.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x0049FC00 + dword PathFindingState::pathFindingRelated(int param_1, uint param_2, uint param_3, int param_4) + { + uint uVar5; + int iVar8; + dword dVar6 = 1000; + uint local_1c = 1000; + dword local_14 = 0; + int local_18 = 10000; + if (param_2 > 399 || param_3 > 399) { + return (dword)(dVar6); + } + if (DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[param_3 * 400 + param_2] == '\0') { + return (dword)(dVar6); + } + this->calculations = this->calculations + 1; + this->searchGeneration = this->searchGeneration + 1; + if (32000 < this->searchGeneration) { + this->searchGeneration = 1; + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 0x27420, '\0', (void*)((int)(DAT_TileMapState::instance.WalkLayer))); + } + this->searchQueue.readIndex = 0; + this->searchQueue.writeIndex = 1; + this->searchQueue.currentDistance = 1; + this->searchQueue.yQueue[0] = (short)param_3; + this->searchQueue.xQueue[0] = (short)param_2; + this->searchQueue.tilesQueue[0] + = DAT_ViewportRenderState::instance.translationMatrix[param_3].addXgetTile + param_2; + int bVar1 + = DAT_TileMapState::instance.SEC_PathfindingCostTileMap1105[param_4][this->searchQueue.tilesQueue[0]]; + DAT_TileMapState::instance.WalkLayer[this->searchQueue.tilesQueue[0]] = (short)this->searchGeneration; + DAT_TileMapState::instance.CertainPathLayer[this->searchQueue.tilesQueue[0]] = 1; + if (this->searchQueue.readIndex != this->searchQueue.writeIndex) { + while (uVar5 = this->searchQueue.tilesQueue[this->searchQueue.readIndex], uVar5 <= 0x13a0f) { + short sVar2 = this->searchQueue.xQueue[this->searchQueue.readIndex]; + this->searchQueue.currentDistance = (int)DAT_TileMapState::instance.CertainPathLayer[uVar5]; + short sVar3 = this->searchQueue.yQueue[this->searchQueue.readIndex]; + int iVar7 = (int)sVar3; + if (0x13a10 < (int)this->searchQueue.currentDistance + || (int)this->searchQueue.currentDistance > param_1) + break; + for (int iVar10 = 0; iVar10 < 8; iVar10 = iVar10 + 1) { + if ((DAT_TileMapState::instance.PathLinkageLayer[uVar5] + & DAT_ClimbLogicDefinedData::instance.BitFlagHelperForPathLinkage[iVar10]) + != 0 + && (dVar6 = DAT_TileMapState::instance.directionTranslationMatrix[iVar7][iVar10] + uVar5, + DAT_TileMapState::instance.WalkLayer[dVar6] != this->searchGeneration)) { + uint uVar9 + = (uint)DAT_TileMapState::instance.SEC_PathfindingCostTileMap1105[param_4][dVar6]; + if (uVar9 < 4) { + uVar9 = 0; + LAB_0049fdba: + if (uVar9 == local_1c + && (iVar8 + = MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::DirectionAlgorithmState_Func:: + setAxisBasedDistanceResult, + DAT_DirectionAlgorithmState::ptr)(param_2, (int)(param_3), + (int)(DAT_TerrainDefinedData::instance + .clockwiseCardinalTranslationMatrix[iVar10] + .int_.xOffset + + sVar2), + DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[iVar10] + .int_.yOffset + + iVar7), + iVar8 < local_18)) + goto LAB_0049fdee; + } else { + if (uVar9 == 0 || (int)local_1c <= (int)uVar9) + goto LAB_0049fdba; + iVar8 = MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::DirectionAlgorithmState_Func::setAxisBasedDistanceResult, + DAT_DirectionAlgorithmState::ptr)(param_2, (int)(param_3), + (int)(DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[iVar10] + .int_.xOffset + + sVar2), + DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[iVar10] + .int_.yOffset + + iVar7); + LAB_0049fdee: + local_1c = uVar9; + local_18 = iVar8; + local_14 = dVar6; + } + short sVar4 = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[iVar10] + .short_.xOffset; + DAT_TileMapState::instance.CertainPathLayer[dVar6] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[dVar6] = (short)this->searchGeneration; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[iVar10] + .short_.yOffset + + sVar3; + this->searchQueue.xQueue[this->searchQueue.writeIndex] = sVar4 + sVar2; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = dVar6; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + } + this->searchQueue.readIndex = this->searchQueue.readIndex + 1; + if (0x13a10 <= (int)this->searchQueue.readIndex) { + this->searchQueue.readIndex = 0; + } + if (this->searchQueue.readIndex == this->searchQueue.writeIndex) + break; + } + } + this->field51_0x9c = bVar1 - local_1c; + dVar6 = local_14; + return (dword)(dVar6); + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/pathFindingResultBased.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/pathFindingResultBased.cpp new file mode 100644 index 0000000000..0c3a244a89 --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/pathFindingResultBased.cpp @@ -0,0 +1,62 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_TribesState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x00497080 + dword PathFindingState::pathFindingResultBased(int param_1, int x, int y, int extraDistance) + { + int* _tilesPointer; + int _index; + int _distance; + int _tile; + int _startWalk = (short)DAT_TileMapState::instance.WalkLayer[this->searchQueue.tilesQueue[0]]; + _tilesPointer = this->searchQueue.tilesQueue + DAT_TribesState::instance.ALG_ResultTileIndex; + _index = DAT_TribesState::instance.ALG_ResultTileIndex; + do { + _tile = *_tilesPointer; + if ((DAT_TileMapState::instance.LogicLayer[_tile] & 0x10000100U) != 0 + && (_distance = (short)DAT_TileMapState::instance.CertainPathLayer[_tile], 0 < _distance)) { + if (extraDistance + 0xc < _distance) { + return (dword)(0); + } + uint _someX = (_tile + - DAT_ViewportRenderState::instance + .translationMatrix[DAT_ViewportRenderState::instance + .tileTranslationMatrix_YComponent[_tile]] + .addXgetTile) + - x; + uint _someY = (short)DAT_ViewportRenderState::instance.tileTranslationMatrix_YComponent[_tile] - y; + if ((abs(_someY) + abs(_someX)) % param_1 == 0 && _distance < 4000) { + dword dVar1 = this->searchQueue.tilesQueue[_index]; + DAT_TribesState::instance.ALG_ResultY = (int)this->searchQueue.yQueue[_index]; + DAT_TribesState::instance.ALG_ResultTileIndex = _index; + DAT_TribesState::instance.ALG_ResultX = dVar1 + - DAT_ViewportRenderState::instance.translationMatrix[DAT_TribesState::instance.ALG_ResultY] + .addXgetTile; + return (dword)(dVar1); + } + } + _index = _index + 1; + _tilesPointer = _tilesPointer + 1; + if (4000 < _index) { + return (dword)(0); + } + } while ((short)DAT_TileMapState::instance.WalkLayer[_tile] == _startWalk); + return (dword)(0); + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/pathFindingToAttackCastleIncludingMoat.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/pathFindingToAttackCastleIncludingMoat.cpp new file mode 100644 index 0000000000..0d4a777f43 --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/pathFindingToAttackCastleIncludingMoat.cpp @@ -0,0 +1,133 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/IO/LowLevelMemory.func.hpp" +#include "OpenSHC/Map/TileMapState.func.hpp" +#include "OpenSHC/Map/Location/Point8ShortXY.hpp" +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_LowLevelMemory.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + + using OpenSHC::Map::Location::Point8ShortXY; + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x004A4140 + BOOLEnum PathFindingState::pathFindingToAttackCastleIncludingMoat( + undefined4 playerID, int wallOwnerPlayerID, uint x, uint y, byte* out_successUnk, int* out_x, int* out_y) + { + this->calculations = this->calculations + 1; + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 0x27420, '\0', (void*)((int)(DAT_TileMapState::instance.CertainPathLayer))); + *out_y = 0; + *out_x = 0; + if (399 < x || 399 < y) { + return FALSE; + } + if (DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[y * 400 + x] == '\0') { + return FALSE; + } + this->searchGeneration = this->searchGeneration + 1; + if (32000 < this->searchGeneration) { + this->searchGeneration = 1; + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 0x27420, '\0', (void*)((int)(DAT_TileMapState::instance.WalkLayer))); + } + this->searchQueue.readIndex = 0; + this->searchQueue.writeIndex = 1; + this->searchQueue.currentDistance = 1; + this->searchQueue.yQueue[0] = (short)y; + this->searchQueue.xQueue[0] = (short)x; + this->searchQueue.tilesQueue[0] = DAT_ViewportRenderState::instance.translationMatrix[y].addXgetTile + x; + DAT_TileMapState::instance.WalkLayer[this->searchQueue.tilesQueue[0]] = (short)this->searchGeneration; + DAT_TileMapState::instance.CertainPathLayer[this->searchQueue.tilesQueue[0]] = 1; + while (this->searchQueue.readIndex != this->searchQueue.writeIndex) { + int _currentTile = this->searchQueue.tilesQueue[this->searchQueue.readIndex]; + if ((_currentTile < 0) || (0x13a10 <= _currentTile)) { + return FALSE; + } + int _currentX = (int)this->searchQueue.xQueue[this->searchQueue.readIndex]; + int _currentY = (int)this->searchQueue.yQueue[this->searchQueue.readIndex]; + if ((DAT_TileMapState::instance.LogicLayer[_currentTile] & 0x100) != 0 + && (DAT_TileMapState::instance.LogicLayer[_currentTile] & 2) == 0 + && wallOwnerPlayerID == (DAT_TileMapState::instance.WallOwnerLayer[_currentTile] & 7) + 1) { + *out_successUnk = 1; + *out_x = (int)_currentX; + *out_y = (int)_currentY; + return TRUE; + } + this->searchQueue.currentDistance = (int)DAT_TileMapState::instance.CertainPathLayer[_currentTile]; + /* + Check all directions for movement + */ + for (int _direction = 0; _direction < 8; _direction = _direction + 2) { + int _nextTile + = DAT_TileMapState::instance.directionTranslationMatrix[_currentY][_direction] + _currentTile; + if (DAT_TileMapState::instance.WalkLayer[_nextTile] == this->searchGeneration + || (DAT_TileMapState::instance.LogicLayer[_nextTile] & 0x31) != 0 + || (((DAT_TileMapState::instance.LogicLayer[_nextTile] & 0x100000) != 0) + && ((DAT_TileMapState::instance.LogicLayer[_nextTile] & 0x200000) == 0)) + || (char)DAT_TileMapState::instance.LogicLayer[_nextTile] < 0 + || (DAT_TileMapState::instance.LogicLayer[_nextTile] & 0x1000) != 0) { + continue; + } + if (DAT_TileMapState::instance.BuildingLayer[_nextTile] != 0 + && 2 < (uint)((short)DAT_BuildingsState::instance + .buildings[DAT_TileMapState::instance.BuildingLayer[_nextTile]] + .buildingType + - 0x4a)) { + continue; + } + if ((DAT_TileMapState::instance.LogicLayer[_nextTile] & 0x40000000) != 0) { + int _moatID = MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::returnMoatIDForPlayerIDs, + DAT_TileMapState::ptr)(_nextTile, wallOwnerPlayerID); + if (_moatID != 0) { + *out_successUnk = 0; + *out_y = (int)DAT_ViewportRenderState::instance.tileTranslationMatrix_YComponent[_nextTile]; + *out_x = _nextTile + - DAT_ViewportRenderState::instance + .translationMatrix[DAT_ViewportRenderState::instance + .tileTranslationMatrix_YComponent[_nextTile]] + .addXgetTile; + return TRUE; + } + continue; + } + DAT_TileMapState::instance.CertainPathLayer[_nextTile] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[_nextTile] = (short)this->searchGeneration; + this->searchQueue.xQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction].short_.xOffset + + _currentX; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction].short_.yOffset + + _currentY; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = _nextTile; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + this->searchQueue.readIndex = this->searchQueue.readIndex + 1; + if (0x13a10 <= (int)this->searchQueue.readIndex) { + this->searchQueue.readIndex = 0; + } + } + return FALSE; + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/pathFindingWithBuildingsIncluded.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/pathFindingWithBuildingsIncluded.cpp new file mode 100644 index 0000000000..bbd6c6f5c2 --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/pathFindingWithBuildingsIncluded.cpp @@ -0,0 +1,275 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/IO/LowLevelMemory.func.hpp" +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +#include "OpenSHC/Globals/DAT_ClimbLogicDefinedData.hpp" +#include "OpenSHC/Globals/DAT_LowLevelMemory.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + /* + WARNING: Removing unreachable block (ram,0x00498700) + */ + /* + WARNING: Removing unreachable block (ram,0x00498713) + */ + /* + WARNING: Removing unreachable block (ram,0x0049871e) + */ + /* + WARNING: Removing unreachable block (ram,0x0049872d) + */ + /* + WARNING: Removing unreachable block (ram,0x00498739) + */ + /* + WARNING: Removing unreachable block (ram,0x00498745) + */ + /* + WARNING: Removing unreachable block (ram,0x00498749) + */ + /* + WARNING: Removing unreachable block (ram,0x00498907) + */ + /* + WARNING: Removing unreachable block (ram,0x0049891a) + */ + /* + WARNING: Removing unreachable block (ram,0x00498925) + */ + /* + WARNING: Removing unreachable block (ram,0x00498934) + */ + /* + WARNING: Removing unreachable block (ram,0x00498940) + */ + /* + WARNING: Removing unreachable block (ram,0x0049894c) + */ + /* + WARNING: Removing unreachable block (ram,0x00498950) + */ + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x00498400 + BOOLEnum PathFindingState::pathFindingWithBuildingsIncluded( + uint x, uint y, uint x2, uint y2, int maxOptionsToTry, int zeroMeansResetAlgorithm) + { + uint uVar1; + int _nextTileOption; + uint uVar3; + uint _tile2; + if (399 < x || 399 < y) { + return FALSE; + } + if (DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[y * 400 + x] == '\0') { + return FALSE; + } + if (x2 == 0xffffffff + || ((x2 <= 399 && (y2 <= 399)) + && (DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[y2 * 400 + x2] != '\0'))) { + if (zeroMeansResetAlgorithm == 0) { + this->searchGeneration = this->searchGeneration + 1; + if (32000 < this->searchGeneration) { + this->searchGeneration = 1; + MACRO_CALL_MEMBER( + OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 0x27420, '\0', (void*)((int)(DAT_TileMapState::instance.WalkLayer))); + } + this->searchQueue.writeIndex = 1; + this->searchQueue.readIndex = 0; + this->searchQueue.currentDistance = 1; + } + this->DAT_Ass = this->DAT_Ass + 1; + this->searchQueue.yQueue[0] = (short)y; + this->searchQueue.xQueue[0] = (short)x; + this->searchQueue.tilesQueue[0] + = DAT_ViewportRenderState::instance.translationMatrix[y].addXgetTile + x; + DAT_TileMapState::instance.CertainPathLayer[this->searchQueue.tilesQueue[0]] + = (short)this->searchQueue.currentDistance; + DAT_TileMapState::instance.WalkLayer[this->searchQueue.tilesQueue[0]] = (short)this->searchGeneration; + if (x2 == 0xffffffff) { + _tile2 = 0; + } else { + _tile2 = DAT_ViewportRenderState::instance.translationMatrix[y2].addXgetTile + x2; + } + if (this->searchQueue.readIndex != this->searchQueue.writeIndex) { + while (true) { + uint _currentTile = this->searchQueue.tilesQueue[this->searchQueue.readIndex]; + if (_currentTile == _tile2) { + return TRUE; + } + if ((this->searchQueue.readIndex >= maxOptionsToTry) || (80400 <= _currentTile)) + break; + int _currentX = this->searchQueue.xQueue[this->searchQueue.readIndex]; + int _currentY = this->searchQueue.yQueue[this->searchQueue.readIndex]; + this->searchQueue.currentDistance + = (int)DAT_TileMapState::instance.CertainPathLayer[_currentTile]; + if (400 < (int)this->searchQueue.currentDistance) { + return FALSE; + } + int _buildingID = DAT_TileMapState::instance.BuildingLayer[_currentTile]; + uint _logical = DAT_TileMapState::instance.LogicLayer[_currentTile]; + for (int _direction = 0; _direction < 8; _direction = _direction + 4) { + _nextTileOption + = DAT_TileMapState::instance.directionTranslationMatrix[_currentY][_direction] + + _currentTile; + if (DAT_TileMapState::instance.WalkLayer[_nextTileOption] != this->searchGeneration + && ((DAT_TileMapState::instance.PathLinkageLayer[_currentTile] + & DAT_ClimbLogicDefinedData::instance.BitFlagHelperForPathLinkage[_direction]) + != 0 + || (((_direction) & 1) == 0 + && (uVar1 = DAT_TileMapState::instance.LogicLayer[_nextTileOption], + (uVar1 & 0x4a5014b1) == 0) + && _buildingID == 0 + && DAT_TileMapState::instance.BuildingLayer[_nextTileOption] == 0 + && (uVar3 = _logical & 0x100, uVar3 == 0 || (uVar1 & 0x100) == 0) + && (uVar3 != 0 || (uVar1 & 0x100) != 0)))) { + DAT_TileMapState::instance.CertainPathLayer[_nextTileOption] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[_nextTileOption] = (short)this->searchGeneration; + this->searchQueue.xQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction] + .short_.xOffset + + _currentX; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction] + .short_.yOffset + + _currentY; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = _nextTileOption; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + _nextTileOption + = DAT_TileMapState::instance.directionTranslationMatrix[_currentY][_direction + 1] + + _currentTile; + if (DAT_TileMapState::instance.WalkLayer[_nextTileOption] != this->searchGeneration + && ((DAT_TileMapState::instance.PathLinkageLayer[_currentTile] + & DAT_ClimbLogicDefinedData::instance + .BitFlagHelperForPathLinkage[_direction + 1]) + != 0 + || (((_direction + 1) & 1) == 0 + && (uVar1 = DAT_TileMapState::instance.LogicLayer[_nextTileOption], + (uVar1 & 0x4a5014b1) == 0) + && _buildingID == 0 + && DAT_TileMapState::instance.BuildingLayer[_nextTileOption] == 0 + && (uVar3 = _logical & 0x100, uVar3 == 0 || (uVar1 & 0x100) == 0) + && (uVar3 != 0 || (uVar1 & 0x100) != 0)))) { + DAT_TileMapState::instance.CertainPathLayer[_nextTileOption] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[_nextTileOption] = (short)this->searchGeneration; + this->searchQueue.xQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance + .clockwiseCardinalTranslationMatrix[_direction + 1] + .short_.xOffset + + _currentX; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance + .clockwiseCardinalTranslationMatrix[_direction + 1] + .short_.yOffset + + _currentY; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = _nextTileOption; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + _nextTileOption + = DAT_TileMapState::instance.directionTranslationMatrix[_currentY][_direction + 2] + + _currentTile; + if (DAT_TileMapState::instance.WalkLayer[_nextTileOption] != this->searchGeneration + && ((DAT_TileMapState::instance.PathLinkageLayer[_currentTile] + & DAT_ClimbLogicDefinedData::instance + .BitFlagHelperForPathLinkage[_direction + 2]) + != 0 + || (((_direction + 2) & 1) == 0 + && (uVar1 = DAT_TileMapState::instance.LogicLayer[_nextTileOption], + (uVar1 & 0x4a5014b1) == 0) + && _buildingID == 0 + && DAT_TileMapState::instance.BuildingLayer[_nextTileOption] == 0 + && (uVar3 = _logical & 0x100, uVar3 == 0 || (uVar1 & 0x100) == 0) + && (uVar3 != 0 || (uVar1 & 0x100) != 0)))) { + DAT_TileMapState::instance.CertainPathLayer[_nextTileOption] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[_nextTileOption] = (short)this->searchGeneration; + this->searchQueue.xQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance + .clockwiseCardinalTranslationMatrix[_direction + 2] + .short_.xOffset + + _currentX; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance + .clockwiseCardinalTranslationMatrix[_direction + 2] + .short_.yOffset + + _currentY; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = _nextTileOption; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + _nextTileOption + = DAT_TileMapState::instance.directionTranslationMatrix[_currentY][_direction + 3] + + _currentTile; + if (DAT_TileMapState::instance.WalkLayer[_nextTileOption] != this->searchGeneration + && ((DAT_TileMapState::instance.PathLinkageLayer[_currentTile] + & DAT_ClimbLogicDefinedData::instance + .BitFlagHelperForPathLinkage[_direction + 3]) + != 0 + || (((_direction + 3) & 1) == 0 + && (uVar1 = DAT_TileMapState::instance.LogicLayer[_nextTileOption], + (uVar1 & 0x4a5014b1) == 0) + && _buildingID == 0 + && DAT_TileMapState::instance.BuildingLayer[_nextTileOption] == 0 + && (uVar3 = _logical & 0x100, uVar3 == 0 || (uVar1 & 0x100) == 0) + && (uVar3 != 0 || (uVar1 & 0x100) != 0)))) { + DAT_TileMapState::instance.CertainPathLayer[_nextTileOption] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[_nextTileOption] = (short)this->searchGeneration; + this->searchQueue.xQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance + .clockwiseCardinalTranslationMatrix[_direction + 3] + .short_.xOffset + + _currentX; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance + .clockwiseCardinalTranslationMatrix[_direction + 3] + .short_.yOffset + + _currentY; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = _nextTileOption; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + } + this->searchQueue.readIndex = this->searchQueue.readIndex + 1; + if (0x13a10 <= (int)this->searchQueue.readIndex) { + this->searchQueue.readIndex = 0; + } + if (this->searchQueue.readIndex == this->searchQueue.writeIndex) { + return FALSE; + } + } + } + } + return FALSE; + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/pathPlanningForTribe.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/pathPlanningForTribe.cpp new file mode 100644 index 0000000000..fe8b812970 --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/pathPlanningForTribe.cpp @@ -0,0 +1,243 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/IO/LowLevelMemory.func.hpp" +#include "OpenSHC/Map/Buildings/BuildingsState.func.hpp" +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" +#include "OpenSHC/Map/Units/TribesState.func.hpp" +#include "OpenSHC/Map/Location/Point8ShortXY.hpp" +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_LowLevelMemory.hpp" +#include "OpenSHC/Globals/DAT_PathFindingState.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_TribesState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + + using OpenSHC::Map::Location::Point8ShortXY; + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + /* + WARNING: Type propagation algorithm not settling + */ + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x004A79A0 + void PathFindingState::pathPlanningForTribe( + uint tribeID, undefined4 targetUnitID, uint x, uint y, int unitCount, dword area, int playerID) + { + int iVar5; + BOOLEnum BVar6; + int (*paiVar9)[8]; + int* _pDest2; + uint uVar11; + int* _pDest3; + int iVar12; + int _destIndex; + int* _pDest1; + _destIndex = 0; + BOOL _assasinsTribe = MACRO_CALL_MEMBER( + OpenSHC::Map::Units::TribesState_Func::isTribeAllAssassins, DAT_TribesState::ptr)(tribeID); + if (399 < x) { + return; + } + if (399 < y) { + return; + } + if (DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[y * 400 + x] == '\0') { + return; + } + this->searchGeneration = this->searchGeneration + 1; + if (32000 < this->searchGeneration) { + this->searchGeneration = 1; + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 0x27420, '\0', (void*)((int)(DAT_TileMapState::instance.WalkLayer))); + } + unitCount = unitCount * 2; + if (500 < unitCount) { + unitCount = 500; + } else if (unitCount < 50) { + unitCount = 50; + } + this->searchQueue.readIndex = 0; + this->searchQueue.writeIndex = 1; + this->searchQueue.currentDistance = 1; + this->searchQueue.yQueue[0] = (short)y; + this->searchQueue.xQueue[0] = (short)x; + int iVar4 = DAT_ViewportRenderState::instance.translationMatrix[y].addXgetTile + x; + this->searchQueue.tilesQueue[0] = iVar4; + DAT_TileMapState::instance.CertainPathLayer[iVar4] = 1; + DAT_TileMapState::instance.WalkLayer[this->searchQueue.tilesQueue[0]] = (short)this->searchGeneration; + if (this->searchQueue.readIndex != this->searchQueue.writeIndex) { + while (uVar11 = this->searchQueue.tilesQueue[this->searchQueue.readIndex], uVar11 <= 0x13a0f) { + int sVar2 = (int)this->searchQueue.yQueue[this->searchQueue.readIndex]; + int sVar1 = (int)this->searchQueue.xQueue[this->searchQueue.readIndex]; + this->searchQueue.currentDistance = (int)DAT_TileMapState::instance.CertainPathLayer[uVar11]; + if ((0x13a10 < (int)this->searchQueue.currentDistance) + || (10 < (int)this->searchQueue.currentDistance)) + break; + for (int _direction = 0; _direction < 8; _direction = _direction + 1) { + iVar12 = DAT_TileMapState::instance.directionTranslationMatrix[sVar2][_direction] + uVar11; + if (DAT_TileMapState::instance.WalkLayer[iVar12] != this->searchGeneration + && ((area == (int)(short)DAT_TileMapState::instance.PathConnectionLayer[iVar12] + || (iVar5 = MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func:: + calculateCanPlayerUnitsNavigateToAreaFromArea, + DAT_PathFindingState::ptr)(playerID, (dword)((int)(area)), + (dword)((int)(( + int)(short)DAT_TileMapState::instance.PathConnectionLayer[iVar12])), + 0), + iVar5 != 0)) + || ((_assasinsTribe != 0 + && (BVar6 = MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func:: + calculateCanReachUsingCachedAreaLogic, + DAT_PathFindingState::ptr)(iVar4, iVar12), + BVar6 != FALSE))))) { + short sVar3 + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction] + .short_.xOffset; + DAT_TileMapState::instance.CertainPathLayer[iVar12] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[iVar12] = (short)this->searchGeneration; + this->searchQueue.xQueue[this->searchQueue.writeIndex] = sVar3 + sVar1; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction] + .short_.yOffset + + sVar2; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = iVar12; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + } + + this->searchQueue.readIndex = this->searchQueue.readIndex + 1; + if (0x13a10 <= (int)this->searchQueue.readIndex) { + this->searchQueue.readIndex = 0; + } + if (this->searchQueue.readIndex == this->searchQueue.writeIndex) + break; + } + } + this->searchQueue.readIndex = 0; + if (0 < (int)this->searchQueue.writeIndex) { + _pDest1 = &this->searchQueue.destinationsArray[0].tile2OrAHelper; + do { + /* + warning + */ + tribeID = (uint)DAT_TileMapState::instance.HeightLayer[iVar4]; + if ((DAT_TileMapState::instance.LogicLayer[iVar4] & 0x10000000U) != 0) { + iVar12 = MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::getBuildingHeightForBuildingID, + DAT_BuildingsState::ptr)((int)DAT_TileMapState::instance.BuildingLayer[iVar4]); + tribeID = tribeID + iVar12; + } + iVar12 = this->searchQueue.tilesQueue[this->searchQueue.readIndex]; + uVar11 = (uint)DAT_TileMapState::instance.HeightLayer[iVar12]; + if ((DAT_TileMapState::instance.LogicLayer[iVar12] & 0x10000000U) != 0) { + iVar12 = MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::getBuildingHeightForBuildingID, + DAT_BuildingsState::ptr)((int)DAT_TileMapState::instance.BuildingLayer[iVar12]); + uVar11 = uVar11 + iVar12; + } + iVar5 = abs(y - (int)this->searchQueue.yQueue[this->searchQueue.readIndex]); + iVar12 = abs(x - (int)this->searchQueue.xQueue[this->searchQueue.readIndex]); + if (iVar12 <= iVar5) { + iVar12 = iVar5; + } + if (iVar12 == 2 && (abs(tribeID - uVar11) < 0x20)) { + _pDest1[-1] = this->searchQueue.tilesQueue[this->searchQueue.readIndex]; + _destIndex = _destIndex + 1; + *_pDest1 = 1; + _pDest1 = _pDest1 + 3; + if (_destIndex >= unitCount) { + return; + } + } + this->searchQueue.readIndex = this->searchQueue.readIndex + 1; + } while (this->searchQueue.readIndex < this->searchQueue.writeIndex); + if (4 < _destIndex) + goto LAB_004a7e8c; + } + this->searchQueue.readIndex = 0; + if (0 < (int)this->searchQueue.writeIndex) { + _pDest2 + = &((PathFindingStatePartB*)(this->climbData + 200))->destinationsArray[_destIndex].tile2OrAHelper; + do { + tribeID = (uint)DAT_TileMapState::instance.HeightLayer[iVar4]; + if ((DAT_TileMapState::instance.LogicLayer[iVar4] & 0x10000000U) != 0) { + iVar12 = MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::getBuildingHeightForBuildingID, + DAT_BuildingsState::ptr)((int)DAT_TileMapState::instance.BuildingLayer[iVar4]); + tribeID = tribeID + iVar12; + } + iVar12 = this->searchQueue.tilesQueue[this->searchQueue.readIndex]; + uVar11 = (uint)DAT_TileMapState::instance.HeightLayer[iVar12]; + if ((DAT_TileMapState::instance.LogicLayer[iVar12] & 0x10000000U) != 0) { + iVar12 = MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::getBuildingHeightForBuildingID, + DAT_BuildingsState::ptr)((int)DAT_TileMapState::instance.BuildingLayer[iVar12]); + uVar11 = uVar11 + iVar12; + } + iVar5 = abs(y - (int)this->searchQueue.yQueue[this->searchQueue.readIndex]); + iVar12 = abs(x - (int)this->searchQueue.xQueue[this->searchQueue.readIndex]); + if (iVar12 <= iVar5) { + iVar12 = iVar5; + } + if (iVar12 == 1 && (abs(tribeID - uVar11) < 0x20)) { + _destIndex = _destIndex + 1; + ((PathHelper12*)(_pDest2 + -1))->tile1 + = this->searchQueue.tilesQueue[this->searchQueue.readIndex]; + *_pDest2 = 1; + _pDest2 = _pDest2 + 3; + if (_destIndex >= unitCount) { + return; + } + } + this->searchQueue.readIndex = this->searchQueue.readIndex + 1; + } while (this->searchQueue.readIndex < this->searchQueue.writeIndex); + } + LAB_004a7e8c: + this->searchQueue.readIndex = 0; + if (0 < (int)this->searchQueue.writeIndex) { + _pDest3 + = &((PathFindingStatePartB*)(this->climbData + 200))->destinationsArray[_destIndex].tile2OrAHelper; + do { + uint _yDiff3 = y - (int)this->searchQueue.yQueue[this->searchQueue.readIndex]; + iVar12 = abs(_yDiff3); + uint _xDiff3 = x - (int)this->searchQueue.xQueue[this->searchQueue.readIndex]; + iVar4 = abs(_xDiff3); + if (iVar4 <= iVar12) { + iVar4 = iVar12; + } + if (2 < iVar4) { + ((PathHelper12*)(_pDest3 + -1))->tile1 + = this->searchQueue.tilesQueue[this->searchQueue.readIndex]; + _destIndex = _destIndex + 1; + *_pDest3 = 0; + _pDest3 = _pDest3 + 3; + if (_destIndex >= unitCount) { + return; + } + } + this->searchQueue.readIndex = this->searchQueue.readIndex + 1; + } while (this->searchQueue.readIndex < this->searchQueue.writeIndex); + } + this->searchQueue.destinationsArray[_destIndex].tile1 = 0; + ((PathFindingStatePartB*)(this->climbData + 200))->destinationsArray[_destIndex].tile2OrAHelper = 0; + return; + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/pathfindingForAttacksUnk.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/pathfindingForAttacksUnk.cpp new file mode 100644 index 0000000000..0392348f0f --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/pathfindingForAttacksUnk.cpp @@ -0,0 +1,198 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/Map/Buildings/BuildingsState.func.hpp" +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" +#include "OpenSHC/Map/Units/TribesState.func.hpp" +#include "OpenSHC/Map/Navigation/Algorithms/XYPair.hpp" +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +#include "OpenSHC/Globals/DAT_BuildingDefinedData.hpp" +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_ClimbLogicDefinedData.hpp" +#include "OpenSHC/Globals/DAT_PathFindingState.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_TribesState.hpp" +#include "OpenSHC/Globals/DAT_UnitsState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + + using OpenSHC::Map::Navigation::Algorithms::XYPair; + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x004A75B0 + void PathFindingState::pathfindingForAttacksUnk( + int tribeID, int buildingID, int param_3, dword param_4, int param_5) + { + uint uVar5; + BOOLEnum BVar6; + XYPair* pXVar8; + uint uVar9; + int iVar10; + int* piVar11; + int iVar12; + int iVar13; + int iVar14; + int iVar15; + int tile2; + int local_28; + int* local_24; + int local_20; + int iVar3 = (int)(short)DAT_BuildingsState::instance.buildings[buildingID].y; + uint uVar7 = DAT_BuildingsState::instance.buildings[buildingID].widthOrHeight; + iVar10 = (int)(short)DAT_BuildingsState::instance.buildings[buildingID].x; + int bVar1 = DAT_TileMapState::instance.DefaultHeightLayer[DAT_BuildingsState::instance.buildings[buildingID] + .currentTilePositionAdjusted]; + int sVar2 = DAT_TribesState::instance.tribes[tribeID].selectionTargetUnitID; + local_28 = 0; + BOOLEnum BVar4 = MACRO_CALL_MEMBER( + OpenSHC::Map::Units::TribesState_Func::isTribeAllAssassins, DAT_TribesState::ptr)(tribeID); + param_3 = param_3 * 2; + if (500 < param_3) { + param_3 = 500; + } else if (param_3 < 0x32) { + param_3 = 0x32; + } + iVar14 = DAT_BuildingDefinedData::instance.BuildingAccessibleTilesCount[uVar7]; + local_20 = 0; + tribeID = 0; + if (0 < iVar14) { + local_24 = &this->searchQueue.destinationsArray[0].tile2OrAHelper; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::setupBuildingEntrancesOffset, + DAT_BuildingsState::ptr)(uVar7, 1, local_20, 0); + iVar12 = DAT_ViewportRenderState::instance + .translationMatrix[iVar3 + DAT_BuildingsState::instance.DAT_TempYOffset] + .addXgetTile + + DAT_BuildingsState::instance.DAT_TempXOffset; + iVar13 = iVar12 + iVar10; + uVar5 = (uint)bVar1 - (uint)DAT_TileMapState::instance.HeightLayer[iVar12 + iVar10]; + uVar9 = (int)uVar5 >> 0x1f; + if ((int)((uVar5 ^ uVar9) - uVar9) < 0x20 + && (((int)(short)DAT_TileMapState::instance.PathConnectionLayer[iVar13] == param_4 + || (iVar12 = MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func:: + calculateCanPlayerUnitsNavigateToAreaFromArea, + DAT_PathFindingState::ptr)(param_5, (dword)((int)(param_4)), + (dword)(( + int)((int)(short)DAT_TileMapState::instance.PathConnectionLayer[iVar13])), + 0), + iVar12 != 0)) + || ((BVar4 != FALSE + && (BVar6 = MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func:: + calculateCanReachUsingCachedAreaLogic, + DAT_PathFindingState::ptr)(DAT_UnitsState::instance.units[sVar2].tile, iVar13), + BVar6 != FALSE)))) + && (uVar5 = (int)DAT_BuildingsState::instance.buildings[buildingID].terrainHeightUnk + - (uint)DAT_TileMapState::instance.HeightLayer[iVar13], + uVar9 = (int)uVar5 >> 0x1f, (int)((uVar5 ^ uVar9) - uVar9) < 0x10)) { + ((PathHelper12*)(local_24 + -1))->tile1 = iVar13; + *local_24 = 0; + pXVar8 = DAT_ClimbLogicDefinedData::instance.CardinalHorizontalFirstSearchOrder; + do { + iVar12 = DAT_ViewportRenderState::instance + .translationMatrix[pXVar8->y + DAT_BuildingsState::instance.DAT_TempYOffset + + iVar3] + .addXgetTile + + pXVar8->x + DAT_BuildingsState::instance.DAT_TempXOffset + iVar10; + if ((DAT_TileMapState::instance.LogicLayer[iVar12] & 0xf000000U) == 0 + && DAT_TileMapState::instance.BuildingLayer[iVar12] == buildingID) { + *local_24 = iVar12; + break; + } + pXVar8 = pXVar8 + 1; + } while ((int)pXVar8 + < (int)&DAT_ClimbLogicDefinedData::instance.CardinalHorizontalFirstSearchOrder[4]); + local_24 = local_24 + 3; + local_28 = local_28 + 1; + if (local_28 >= param_3) { + return; + } + } + local_20 = local_20 + 1; + if (iVar14 <= local_20) { + local_20 = 0; + } + tribeID = tribeID + 1; + } while (tribeID < iVar14); + } + iVar14 = uVar7 + 1; + if (iVar14 < 0xe) { + local_20 = 0x20; + do { + iVar12 = DAT_BuildingDefinedData::instance.BuildingAccessibleTilesCount[iVar14]; + iVar13 = 0; + tribeID = 0; + if (0 < iVar12) { + piVar11 = &((PathFindingStatePartB*)(this->climbData + 200)) + ->destinationsArray[local_28] + .tile2OrAHelper; + do { + MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::setupBuildingEntrancesOffset, + DAT_BuildingsState::ptr)(iVar14, 1, iVar13, 0); + uVar7 = iVar3 + DAT_BuildingsState::instance.DAT_TempYOffset; + if ((uint)(DAT_BuildingsState::instance.DAT_TempXOffset + iVar10) < 400 && uVar7 <= 399 + && DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[uVar7 * 400 + + DAT_BuildingsState::instance.DAT_TempXOffset + iVar10] + != '\0') { + iVar15 = DAT_ViewportRenderState::instance.translationMatrix[uVar7].addXgetTile + + DAT_BuildingsState::instance.DAT_TempXOffset; + tile2 = iVar15 + iVar10; + uVar7 = (uint)bVar1 - (uint)DAT_TileMapState::instance.HeightLayer[iVar15 + iVar10]; + uVar5 = (int)uVar7 >> 0x1f; + if ((int)((uVar7 ^ uVar5) - uVar5) < 0x20 + && (((int)(short)DAT_TileMapState::instance.PathConnectionLayer[tile2] == param_4 + || (iVar15 + = MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func:: + calculateCanPlayerUnitsNavigateToAreaFromArea, + DAT_PathFindingState::ptr)(param_5, (dword)((int)(param_4)), + (dword)((int)((short)(short)(short) + DAT_TileMapState::instance.PathConnectionLayer[tile2])), + 0), + iVar15 != 0)) + || ((BVar4 != FALSE + && (BVar6 + = MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func:: + calculateCanReachUsingCachedAreaLogic, + DAT_PathFindingState::ptr)( + DAT_UnitsState::instance.units[sVar2].tile, tile2), + BVar6 != FALSE)))) + && (uVar7 = (int)DAT_BuildingsState::instance.buildings[buildingID].terrainHeightUnk + - (uint)DAT_TileMapState::instance.HeightLayer[tile2], + uVar5 = (int)uVar7 >> 0x1f, (int)((uVar7 ^ uVar5) - uVar5) < local_20)) { + local_28 = local_28 + 1; + ((PathHelper12*)(piVar11 + -1))->tile1 = tile2; + *piVar11 = 0; + piVar11 = piVar11 + 3; + if (local_28 >= param_3) { + return; + } + } + iVar13 = iVar13 + 1; + if (iVar12 <= iVar13) { + iVar13 = 0; + } + } + tribeID = tribeID + 1; + } while (tribeID < iVar12); + } + local_20 = local_20 + 0x10; + iVar14 = iVar14 + 1; + } while (iVar14 < 0xe); + } + this->searchQueue.destinationsArray[local_28].tile1 = 0; + ((PathFindingStatePartB*)(this->climbData + 200))->destinationsArray[local_28].tile2OrAHelper = 0; + return; + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/pathfindingRelated49ff20.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/pathfindingRelated49ff20.cpp new file mode 100644 index 0000000000..5607e8ec94 --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/pathfindingRelated49ff20.cpp @@ -0,0 +1,119 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/IO/LowLevelMemory.func.hpp" +#include "OpenSHC/Map/Entities/EntityType.hpp" + +#include "OpenSHC/Globals/DAT_ClimbLogicDefinedData.hpp" +#include "OpenSHC/Globals/DAT_EntityState.hpp" +#include "OpenSHC/Globals/DAT_LowLevelMemory.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_TroopValueState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + + using OpenSHC::Map::Entities::EntityType; + + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x0049FF20 + dword PathFindingState::pathfindingRelated49ff20(uint x, uint y, int playerID, uint distanceUnk, int param_5) + { + int iVar1; + dword dVar4 = 1000; + int local_4 = 1000; + dword local_8 = 0; + if (x > 399 || y > 399) { + return (dword)(dVar4); + } + if (DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[y * 400 + x] == '\0') { + return (dword)(dVar4); + } + this->calculations = this->calculations + 1; + this->searchGeneration = this->searchGeneration + 1; + if (32000 < this->searchGeneration) { + this->searchGeneration = 1; + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 160800, '\0', (void*)((int)(DAT_TileMapState::instance.WalkLayer))); + } + this->searchQueue.readIndex = 0; + this->searchQueue.writeIndex = 1; + this->searchQueue.currentDistance = 1; + this->searchQueue.yQueue[0] = (short)y; + this->searchQueue.tilesQueue[0] = DAT_ViewportRenderState::instance.translationMatrix[y].addXgetTile + x; + DAT_TileMapState::instance.WalkLayer[this->searchQueue.tilesQueue[0]] = (short)this->searchGeneration; + DAT_TileMapState::instance.CertainPathLayer[this->searchQueue.tilesQueue[0]] = 1; + dVar4 = local_8; + while (this->searchQueue.readIndex != this->searchQueue.writeIndex) { + int iVar3 = this->searchQueue.tilesQueue[this->searchQueue.readIndex]; + if (iVar3 < 0) { + return (dword)(local_8); + } + if (0x13a10 <= iVar3) { + return (dword)(local_8); + } + int sVar2 = (int)this->searchQueue.yQueue[this->searchQueue.readIndex]; + this->searchQueue.currentDistance = (int)DAT_TileMapState::instance.CertainPathLayer[iVar3]; + if (0x13a10 < (int)this->searchQueue.currentDistance) { + return (dword)(local_8); + } + for (int iVar5 = 0; iVar5 < 8; iVar5 = iVar5 + 1) { + if ((DAT_TileMapState::instance.PathLinkageLayer[iVar3] + & DAT_ClimbLogicDefinedData::instance.BitFlagHelperForPathLinkage[iVar5]) + != 0 + && (DAT_TileMapState::instance.LogicLayer[iVar3] & 0x10000100U) == 0 + && (dVar4 = DAT_TileMapState::instance.directionTranslationMatrix[sVar2][iVar5] + iVar3, + DAT_TileMapState::instance.WalkLayer[dVar4] != this->searchGeneration)) { + uint uVar6 = (uint)DAT_TileMapState::instance.SEC_TileMap1104[dVar4]; + if (param_5 == 0) { + uVar6 = 0; + } + int _entity = DAT_TileMapState::instance.EntityLayer[dVar4]; + if (((_entity == 0) + || (DAT_EntityState::instance.entityArray[_entity].entityType + != OpenSHC::Map::Entities::ET_FIRE)) + && DAT_TileMapState::instance.SEC_PathfindingCostTileMap1105[*( + int*)((int)DAT_TroopValueState::instance.attackInfo.hackValuesArray + + playerID * 0x177bc + -0x10)][dVar4] + == distanceUnk) { + if ((16 < (int)this->searchQueue.currentDistance) && (local_8 != 0)) { + return (dword)(local_8); + } + if ((10 < (int)this->searchQueue.currentDistance) + && (iVar1 = this->searchQueue.currentDistance + uVar6 * 2, iVar1 < local_4)) { + local_4 = iVar1; + local_8 = dVar4; + } + } + DAT_TileMapState::instance.CertainPathLayer[dVar4] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[dVar4] = (short)this->searchGeneration; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[iVar5].short_.yOffset + + sVar2; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = dVar4; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + } + this->searchQueue.readIndex = this->searchQueue.readIndex + 1; + if (0x13a10 <= (int)this->searchQueue.readIndex) { + this->searchQueue.readIndex = 0; + } + dVar4 = local_8; + } + return (dword)(dVar4); + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/pathfindingUpdate_0x4a8ab0.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/pathfindingUpdate_0x4a8ab0.cpp new file mode 100644 index 0000000000..173c65250a --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/pathfindingUpdate_0x4a8ab0.cpp @@ -0,0 +1,306 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/Audio/SFX/SFXState.func.hpp" +#include "OpenSHC/IO/LowLevelMemory.func.hpp" +#include "OpenSHC/Map/Buildings/BuildingsState.func.hpp" +#include "OpenSHC/Map/Entities/EntityState.func.hpp" +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" +#include "OpenSHC/Map/TileMapState.func.hpp" +#include "OpenSHC/DE/SHCDE/eSFX.hpp" +#include "OpenSHC/Map/Location/Point8IntXY.hpp" + +#include "OpenSHC/Globals/DAT_BuildingDefinedData.hpp" +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_EntityState.hpp" +#include "OpenSHC/Globals/DAT_GameState.hpp" +#include "OpenSHC/Globals/DAT_LowLevelMemory.hpp" +#include "OpenSHC/Globals/DAT_PathFindingState.hpp" +#include "OpenSHC/Globals/DAT_SFXState.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + + using OpenSHC::DE::SHCDE::eSFX; + using OpenSHC::Map::Location::Point8IntXY; + + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x004A8AB0 + void PathFindingState::pathfindingUpdate_0x4a8ab0(int param_1) + { + int uVar1; + int uVar2; + int (*paiVar7)[8]; + int iVar8; + int iVar9; + int iVar10; + int* piVar11; + short* psVar12; + bool bVar13; + int local_24; + short* local_18; + short* local_14; + int* local_10; + this->searchGeneration = this->searchGeneration + 1; + this->calculations = this->calculations + 1; + if (32000 < this->searchGeneration) { + this->searchGeneration = 1; + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 0x27420, '\0', (void*)((int)(DAT_TileMapState::instance.WalkLayer))); + } + this->searchQueue.currentDistance = 1; + this->searchQueue.readIndex = 0; + this->searchQueue.writeIndex = 1; + bVar13 = DAT_GameState::instance.mapAndTime.signpostIDs[0] != 0; + local_24 = 0x9d08; + if (bVar13) { + this->searchQueue.xQueue[0] + = DAT_BuildingsState::instance.buildings[DAT_GameState::instance.mapAndTime.signpostIDs[0]].x; + this->searchQueue.yQueue[0] + = DAT_BuildingsState::instance.buildings[DAT_GameState::instance.mapAndTime.signpostIDs[0]].y; + this->searchQueue.tilesQueue[0] + = DAT_ViewportRenderState::instance.translationMatrix[this->searchQueue.yQueue[0]].addXgetTile + + (int)this->searchQueue.xQueue[0]; + DAT_TileMapState::instance.CertainPathLayer[this->searchQueue.tilesQueue[0]] = 1; + DAT_TileMapState::instance.WalkLayer[this->searchQueue.tilesQueue[0]] = (short)this->searchGeneration; + } + uint uVar6 = (uint)bVar13; + if (DAT_GameState::instance.mapAndTime.signpostIDs[1] != 0) { + uVar1 = DAT_BuildingsState::instance.buildings[DAT_GameState::instance.mapAndTime.signpostIDs[1]].x; + uVar2 = DAT_BuildingsState::instance.buildings[DAT_GameState::instance.mapAndTime.signpostIDs[1]].y; + this->searchQueue.yQueue[uVar6] = uVar2; + this->searchQueue.xQueue[uVar6] = uVar1; + iVar9 = DAT_ViewportRenderState::instance.translationMatrix[uVar2].addXgetTile + uVar1; + this->searchQueue.tilesQueue[uVar6] = iVar9; + DAT_TileMapState::instance.CertainPathLayer[iVar9] = (short)this->searchQueue.currentDistance; + DAT_TileMapState::instance.WalkLayer[this->searchQueue.tilesQueue[uVar6]] + = (short)this->searchGeneration; + uVar6 = uVar6 + 1; + } + if (DAT_GameState::instance.mapAndTime.signpostIDs[2] != 0) { + uVar1 = DAT_BuildingsState::instance.buildings[DAT_GameState::instance.mapAndTime.signpostIDs[2]].x; + uVar2 = DAT_BuildingsState::instance.buildings[DAT_GameState::instance.mapAndTime.signpostIDs[2]].y; + this->searchQueue.yQueue[uVar6] = uVar2; + this->searchQueue.xQueue[uVar6] = uVar1; + iVar9 = DAT_ViewportRenderState::instance.translationMatrix[uVar2].addXgetTile + uVar1; + this->searchQueue.tilesQueue[uVar6] = iVar9; + DAT_TileMapState::instance.CertainPathLayer[iVar9] = (short)this->searchQueue.currentDistance; + DAT_TileMapState::instance.WalkLayer[this->searchQueue.tilesQueue[uVar6]] + = (short)this->searchGeneration; + uVar6 = uVar6 + 1; + } + if (DAT_GameState::instance.mapAndTime.signpostIDs[3] != 0) { + uVar1 = DAT_BuildingsState::instance.buildings[DAT_GameState::instance.mapAndTime.signpostIDs[3]].x; + uVar2 = DAT_BuildingsState::instance.buildings[DAT_GameState::instance.mapAndTime.signpostIDs[3]].y; + this->searchQueue.yQueue[uVar6] = uVar2; + this->searchQueue.xQueue[uVar6] = uVar1; + iVar9 = DAT_ViewportRenderState::instance.translationMatrix[uVar2].addXgetTile + uVar1; + this->searchQueue.tilesQueue[uVar6] = iVar9; + DAT_TileMapState::instance.CertainPathLayer[iVar9] = (short)this->searchQueue.currentDistance; + DAT_TileMapState::instance.WalkLayer[this->searchQueue.tilesQueue[uVar6]] + = (short)this->searchGeneration; + uVar6 = uVar6 + 1; + } + if (DAT_GameState::instance.mapAndTime.signpostIDs[4] != 0) { + uVar1 = DAT_BuildingsState::instance.buildings[DAT_GameState::instance.mapAndTime.signpostIDs[4]].x; + uVar2 = DAT_BuildingsState::instance.buildings[DAT_GameState::instance.mapAndTime.signpostIDs[4]].y; + this->searchQueue.yQueue[uVar6] = uVar2; + this->searchQueue.xQueue[uVar6] = uVar1; + iVar9 = DAT_ViewportRenderState::instance.translationMatrix[uVar2].addXgetTile + uVar1; + this->searchQueue.tilesQueue[uVar6] = iVar9; + DAT_TileMapState::instance.CertainPathLayer[iVar9] = (short)this->searchQueue.currentDistance; + DAT_TileMapState::instance.WalkLayer[this->searchQueue.tilesQueue[uVar6]] + = (short)this->searchGeneration; + uVar6 = uVar6 + 1; + } + if (DAT_GameState::instance.mapAndTime.signpostIDs[5] != 0) { + uVar1 = DAT_BuildingsState::instance.buildings[DAT_GameState::instance.mapAndTime.signpostIDs[5]].x; + uVar2 = DAT_BuildingsState::instance.buildings[DAT_GameState::instance.mapAndTime.signpostIDs[5]].y; + this->searchQueue.yQueue[uVar6] = uVar2; + this->searchQueue.xQueue[uVar6] = uVar1; + iVar9 = DAT_ViewportRenderState::instance.translationMatrix[uVar2].addXgetTile + uVar1; + this->searchQueue.tilesQueue[uVar6] = iVar9; + DAT_TileMapState::instance.CertainPathLayer[iVar9] = (short)this->searchQueue.currentDistance; + DAT_TileMapState::instance.WalkLayer[this->searchQueue.tilesQueue[uVar6]] + = (short)this->searchGeneration; + uVar6 = uVar6 + 1; + } + if (DAT_GameState::instance.mapAndTime.signpostIDs[6] != 0) { + uVar1 = DAT_BuildingsState::instance.buildings[DAT_GameState::instance.mapAndTime.signpostIDs[6]].x; + uVar2 = DAT_BuildingsState::instance.buildings[DAT_GameState::instance.mapAndTime.signpostIDs[6]].y; + this->searchQueue.yQueue[uVar6] = uVar2; + this->searchQueue.xQueue[uVar6] = uVar1; + iVar9 = uVar1 + DAT_ViewportRenderState::instance.translationMatrix[uVar2].addXgetTile; + this->searchQueue.tilesQueue[uVar6] = iVar9; + DAT_TileMapState::instance.WalkLayer[this->searchQueue.tilesQueue[uVar6]] + = (short)this->searchGeneration; + DAT_TileMapState::instance.CertainPathLayer[iVar9] = (short)this->searchQueue.currentDistance; + uVar6 = uVar6 + 1; + } + if (DAT_GameState::instance.mapAndTime.signpostIDs[7] != 0) { + uVar1 = DAT_BuildingsState::instance.buildings[DAT_GameState::instance.mapAndTime.signpostIDs[7]].x; + uVar2 = DAT_BuildingsState::instance.buildings[DAT_GameState::instance.mapAndTime.signpostIDs[7]].y; + this->searchQueue.yQueue[uVar6] = uVar2; + this->searchQueue.xQueue[uVar6] = uVar1; + iVar9 = DAT_ViewportRenderState::instance.translationMatrix[uVar2].addXgetTile + uVar1; + this->searchQueue.tilesQueue[uVar6] = iVar9; + DAT_TileMapState::instance.CertainPathLayer[iVar9] = (short)this->searchQueue.currentDistance; + DAT_TileMapState::instance.WalkLayer[this->searchQueue.tilesQueue[uVar6]] + = (short)this->searchGeneration; + } + if (this->searchQueue.readIndex != this->searchQueue.writeIndex) { + while (uVar6 = this->searchQueue.tilesQueue[this->searchQueue.readIndex], uVar6 <= 0x13a0f) { + int sVar3 = (int)this->searchQueue.xQueue[this->searchQueue.readIndex]; + this->searchQueue.currentDistance = (int)DAT_TileMapState::instance.CertainPathLayer[uVar6]; + int sVar4 = (int)this->searchQueue.yQueue[this->searchQueue.readIndex]; + if (0x13a10 < (int)this->searchQueue.currentDistance + || (int)this->searchQueue.currentDistance > param_1) + break; + local_10 = this->searchQueue.tilesQueue + local_24; + local_18 = this->searchQueue.xQueue + local_24; + local_14 = this->searchQueue.yQueue + local_24; + for (int _direction = 0; _direction < 8; _direction = _direction + 1) { + iVar9 = DAT_TileMapState::instance.directionTranslationMatrix[sVar4][_direction] + uVar6; + uint uVar5 = DAT_TileMapState::instance.LogicLayer[iVar9]; + if (DAT_TileMapState::instance.WalkLayer[iVar9] != this->searchGeneration + && (uVar5 & 0x30) == 0) { + DAT_TileMapState::instance.CertainPathLayer[iVar9] + = (short)this->searchQueue.currentDistance + 1; + iVar8 = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction] + .int_.xOffset; + DAT_TileMapState::instance.WalkLayer[iVar9] = (short)this->searchGeneration; + this->searchQueue.xQueue[this->searchQueue.writeIndex] = iVar8 + sVar3; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = (short)DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction] + .int_.yOffset + + sVar4; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = iVar9; + if (DAT_TileMapState::instance.BuildingLayer[iVar9] != 0) { + iVar8 = (int)DAT_TileMapState::instance.BuildingLayer[iVar9]; + iVar10 = (int)(short)DAT_BuildingsState::instance.buildings[iVar8].buildingType; + switch (iVar10) { + case 10: + case 0xb: + case 0x13: + case 0x24: + case 0x25: + case 0x26: + case 0x28: + case 0x29: + case 0x2a: + case 0x34: + case 0x37: + case 0x47: + case 0x48: + case 0x49: + break; + default: + DAT_TileMapState::instance.showNoRubbleWhenDestroyingBuilding + = (int)(DAT_BuildingDefinedData::instance + .BuildingShowRubbleWhenDestroyed[iVar10] + == 0); + MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::destroyBuilding, + DAT_BuildingsState::ptr)(iVar8); + MACRO_CALL_MEMBER(OpenSHC::Audio::SFX::SFXState_Func::playSFXAtLocation, + DAT_SFXState::ptr)((int)(short)DAT_BuildingsState::instance.buildings[iVar8].x, + (int)((short)DAT_BuildingsState::instance.buildings[iVar8].y), + OpenSHC::DE::SHCDE::FX_BUILDING_SMASH); + } + } + if ((uVar5 & 0x100) != 0 && (uVar5 & 2) == 0) { + MACRO_CALL_MEMBER(OpenSHC::Map::Entities::EntityState_Func::destroyEntitiesOnTile, + DAT_EntityState::ptr)(iVar9); + DAT_TileMapState::instance.LogicLayer[iVar9] + = DAT_TileMapState::instance.LogicLayer[iVar9] & 0xffbef4ff; + iVar8 = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction] + .int_.xOffset; + local_24 = local_24 + 1; + DAT_TileMapState::instance.HeightLayer[iVar9] + = DAT_TileMapState::instance.DefaultHeightLayer[iVar9]; + DAT_TileMapState::instance.DamageLayer[iVar9] = 0; + DAT_PathFindingState::instance.toggleUpdateSeparateAreaTileMap = 1; + DAT_TileMapState::instance.field204_0x554a30 = 1; + *local_18 = iVar8 + sVar3; + *local_14 = (short)DAT_TerrainDefinedData::instance + .clockwiseCardinalTranslationMatrix[_direction] + .int_.yOffset + + sVar4; + *local_10 = iVar9; + local_14 = local_14 + 1; + local_18 = local_18 + 1; + local_10 = local_10 + 1; + } + if ((uVar5 & 0x40000000) != 0) { + MACRO_CALL_MEMBER( + OpenSHC::Map::TileMapState_Func::clearMoatDataAtTile, DAT_TileMapState::ptr)( + DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction] + .int_.xOffset + + (int)sVar3, + (int)(DAT_TerrainDefinedData::instance + .clockwiseCardinalTranslationMatrix[_direction] + .int_.yOffset + + sVar4)); + iVar8 = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction] + .int_.xOffset; + local_24 = local_24 + 1; + DAT_TileMapState::instance.HeightLayer[iVar9] = 8; + DAT_TileMapState::instance.LogicLayer[iVar9] + = DAT_TileMapState::instance.LogicLayer[iVar9] & 0xbfffbfff; + *local_18 = iVar8 + sVar3; + *local_10 = iVar9; + *local_14 = (short)DAT_TerrainDefinedData::instance + .clockwiseCardinalTranslationMatrix[_direction] + .int_.yOffset + + sVar4; + local_18 = local_18 + 1; + local_14 = local_14 + 1; + local_10 = local_10 + 1; + } + if ((uVar5 & 8) != 0) { + DAT_TileMapState::instance.LogicLayer[iVar9] + = DAT_TileMapState::instance.LogicLayer[iVar9] & 0xfffffff7; + } + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + } + + this->searchQueue.readIndex = this->searchQueue.readIndex + 1; + if (0x13a10 <= (int)this->searchQueue.readIndex) { + this->searchQueue.readIndex = 0; + } + if (this->searchQueue.readIndex == this->searchQueue.writeIndex) + break; + } + } + if (0x9d08 < local_24) { + psVar12 = this->searchQueue.yQueue + 0x9d08; + local_24 = local_24 + -0x9d08; + piVar11 = this->searchQueue.tilesQueue + 0x9d08; + do { + MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::PathFindingState_Func::updatePathLinkagesInAllEightDirections, this)( + (int)*psVar12, (int)(*piVar11)); + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::updateWalkAndPathLayer, this)( + 7, (uint)(psVar12[0x13a10]), (uint)((int)*psVar12)); + piVar11 = piVar11 + 1; + psVar12 = psVar12 + 1; + local_24 = local_24 + -1; + } while (local_24 != 0); + } + return; + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/placeCommemoratingStatueAtGoodLocation.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/placeCommemoratingStatueAtGoodLocation.cpp new file mode 100644 index 0000000000..8c796903a5 --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/placeCommemoratingStatueAtGoodLocation.cpp @@ -0,0 +1,195 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/IO/LowLevelMemory.func.hpp" +#include "OpenSHC/Map/TileMapState.func.hpp" +#include "OpenSHC/Random/RNG.func.hpp" +#include "OpenSHC/Commands/MappersEnum.hpp" +#include "OpenSHC/Map/Location/Point8ShortXY.hpp" +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_GameState.hpp" +#include "OpenSHC/Globals/DAT_LowLevelMemory.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" +#include "OpenSHC/Globals/SEC_RNG.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + + using OpenSHC::Commands::MappersEnum; + using OpenSHC::Map::Location::Point8ShortXY; + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + WARNING: Enum "MappersEnumInt": Some values do not have unique names + */ + /* + decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x004A21B0 + void PathFindingState::placeCommemoratingStatueAtGoodLocation(int playerID) + { + int iVar3; + MappersEnum commandBuildingType; + int sVar1 = DAT_GameState::instance.playerDataArray[playerID].someKeepRelatedX2; + uint uVar7 = (uint)sVar1; + int sVar2 = DAT_GameState::instance.playerDataArray[playerID].someKeepRelatedY2; + uint uVar8 = (uint)sVar2; + if (uVar7 > 399 || uVar8 > 399) { + return; + } + if (DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[uVar8 * 400 + uVar7] == '\0') { + return; + } + this->calculations = this->calculations + 1; + this->searchGeneration = this->searchGeneration + 1; + if (32000 < this->searchGeneration) { + this->searchGeneration = 1; + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 0x27420, '\0', (void*)((int)(DAT_TileMapState::instance.WalkLayer))); + } + this->searchQueue.currentDistance = 1; + this->searchQueue.readIndex = 0; + this->searchQueue.writeIndex = 1; + this->searchQueue.yQueue[0] = sVar2; + this->searchQueue.tilesQueue[0] + = DAT_ViewportRenderState::instance.translationMatrix[uVar8].addXgetTile + uVar7; + DAT_TileMapState::instance.WalkLayer[this->searchQueue.tilesQueue[0]] = (short)this->searchGeneration; + this->searchQueue.xQueue[0] = sVar1; + commandBuildingType = (OpenSHC::Commands::MappersEnum)((int)SEC_RNG::instance.currentNumber2 % 5 + + OpenSHC::Commands::M_MAPPER_STATUE1); + DAT_TileMapState::instance.CertainPathLayer[this->searchQueue.tilesQueue[0]] = 1; + MACRO_CALL_MEMBER(OpenSHC::Random::RNG_Func::nextRandomNumber2, SEC_RNG::ptr)(); + if (this->searchQueue.readIndex != this->searchQueue.writeIndex) { + while (true) { + iVar3 = this->searchQueue.tilesQueue[this->searchQueue.readIndex]; + if (iVar3 < 0) { + return; + } + if (0x13a10 <= iVar3) { + return; + } + sVar1 = this->searchQueue.xQueue[this->searchQueue.readIndex]; + sVar2 = this->searchQueue.yQueue[this->searchQueue.readIndex]; + uVar7 = (uint)sVar2; + this->searchQueue.currentDistance = (int)DAT_TileMapState::instance.CertainPathLayer[iVar3]; + if (0x13a10 < (int)this->searchQueue.currentDistance) { + return; + } + if (0x14 < (int)this->searchQueue.currentDistance) { + return; + } + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::checkBuildingCanBePlacedHere, + DAT_TileMapState::ptr)(playerID, (uint)(sVar1), uVar7, commandBuildingType, -2); + if (DAT_TileMapState::instance.buildingPlacementFail == FALSE) + break; + for (int _direction = 0; _direction < 8; _direction = _direction + 4) { + int iVar6 = DAT_TileMapState::instance.directionTranslationMatrix[uVar7][_direction] + iVar3; + if (DAT_TileMapState::instance.WalkLayer[iVar6] != this->searchGeneration + && (DAT_TileMapState::instance.LogicLayer[iVar6] & 0x30) == 0) { + DAT_TileMapState::instance.CertainPathLayer[iVar6] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[iVar6] = (short)this->searchGeneration; + this->searchQueue.xQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction] + .short_.xOffset + + sVar1; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction] + .short_.yOffset + + sVar2; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = iVar6; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + iVar6 = DAT_TileMapState::instance.directionTranslationMatrix[uVar7][_direction + 1] + iVar3; + if (DAT_TileMapState::instance.WalkLayer[iVar6] != this->searchGeneration + && (DAT_TileMapState::instance.LogicLayer[iVar6] & 0x30) == 0) { + DAT_TileMapState::instance.CertainPathLayer[iVar6] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[iVar6] = (short)this->searchGeneration; + this->searchQueue.xQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction + 1] + .short_.xOffset + + sVar1; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction + 1] + .short_.yOffset + + sVar2; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = iVar6; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + iVar6 = DAT_TileMapState::instance.directionTranslationMatrix[uVar7][_direction + 2] + iVar3; + if (DAT_TileMapState::instance.WalkLayer[iVar6] != this->searchGeneration + && (DAT_TileMapState::instance.LogicLayer[iVar6] & 0x30) == 0) { + DAT_TileMapState::instance.CertainPathLayer[iVar6] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[iVar6] = (short)this->searchGeneration; + this->searchQueue.xQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction + 2] + .short_.xOffset + + sVar1; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction + 2] + .short_.yOffset + + sVar2; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = iVar6; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + iVar6 = DAT_TileMapState::instance.directionTranslationMatrix[uVar7][_direction + 3] + iVar3; + if (DAT_TileMapState::instance.WalkLayer[iVar6] != this->searchGeneration + && (DAT_TileMapState::instance.LogicLayer[iVar6] & 0x30) == 0) { + DAT_TileMapState::instance.CertainPathLayer[iVar6] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[iVar6] = (short)this->searchGeneration; + this->searchQueue.xQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction + 3] + .short_.xOffset + + sVar1; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction + 3] + .short_.yOffset + + sVar2; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = iVar6; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + } + + this->searchQueue.readIndex = this->searchQueue.readIndex + 1; + if (0x13a10 <= (int)this->searchQueue.readIndex) { + this->searchQueue.readIndex = 0; + } + if (this->searchQueue.readIndex == this->searchQueue.writeIndex) { + return; + } + } + DAT_TileMapState::instance.skipPlacementCheck = 1; + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::placeBuilding, DAT_TileMapState::ptr)( + playerID, (int)(sVar1), (int)(uVar7), commandBuildingType, 2, 0xf); + iVar3 = DAT_TileMapState::instance.placedBuildingID; + DAT_BuildingsState::instance.buildings[DAT_TileMapState::instance.placedBuildingID].owner = 0; + DAT_BuildingsState::instance.buildings[iVar3].statueCommemoratingPlayerID = (short)playerID; + } + return; + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/populateDestinationsArrayWithWallTileAndFreeTilePairInSameArea.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/populateDestinationsArrayWithWallTileAndFreeTilePairInSameArea.cpp new file mode 100644 index 0000000000..879e062383 --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/populateDestinationsArrayWithWallTileAndFreeTilePairInSameArea.cpp @@ -0,0 +1,186 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/IO/LowLevelMemory.func.hpp" +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" +#include "OpenSHC/Map/Location/Point8ShortXY.hpp" +#include "OpenSHC/Map/Navigation/Algorithms/XYPair.hpp" + +#include "OpenSHC/Globals/DAT_ClimbLogicDefinedData.hpp" +#include "OpenSHC/Globals/DAT_LowLevelMemory.hpp" +#include "OpenSHC/Globals/DAT_PathFindingState.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + using OpenSHC::Map::Location::Point8ShortXY; + using OpenSHC::Map::Navigation::Algorithms::XYPair; + + /* + WARNING: Type propagation algorithm not settling + */ + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x004A83B0 + void PathFindingState::populateDestinationsArrayWithWallTileAndFreeTilePairInSameArea( + int tile, int maxDestinations, dword area, int playerID) + { + int iVar2; + int* piVar3; + XYPair* pXVar4; + int (*paiVar6)[8]; + int _candidate; + int _dIndex; + short _tileY; + int _axgt; + int _tile2; + uint _tile; + int _x; + int _y; + _tileY = (short)DAT_ViewportRenderState::instance.tileTranslationMatrix_YComponent[tile]; + _axgt = DAT_ViewportRenderState::instance.translationMatrix[_tileY].addXgetTile; + _dIndex = 0; + this->searchGeneration = this->searchGeneration + 1; + if (32000 < this->searchGeneration) { + this->searchGeneration = 1; + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 0x27420, '\0', (void*)((int)(DAT_TileMapState::instance.WalkLayer))); + } + this->searchQueue.currentDistance = 1; + this->searchQueue.writeIndex = 1; + this->searchQueue.readIndex = 0; + maxDestinations = maxDestinations * 2; + if (500 < maxDestinations) { + maxDestinations = 500; + } else if (maxDestinations < 50) { + maxDestinations = 50; + } + this->searchQueue.tilesQueue[0] = tile; + this->searchQueue.yQueue[0] = _tileY; + this->searchQueue.xQueue[0] = tile - _axgt; + DAT_TileMapState::instance.WalkLayer[this->searchQueue.tilesQueue[0]] = (short)this->searchGeneration; + DAT_TileMapState::instance.CertainPathLayer[tile] = (short)this->searchQueue.currentDistance; + if (this->searchQueue.readIndex != this->searchQueue.writeIndex) { + while (_tile = this->searchQueue.tilesQueue[this->searchQueue.readIndex], _tile <= 0x13a0f) { + _x = (int)this->searchQueue.xQueue[this->searchQueue.readIndex]; + _y = (int)this->searchQueue.yQueue[this->searchQueue.readIndex]; + this->searchQueue.currentDistance = (int)DAT_TileMapState::instance.CertainPathLayer[_tile]; + if ((80400 < (int)this->searchQueue.currentDistance) + || (10 < (int)this->searchQueue.currentDistance)) + break; + for (int _direction = 0; _direction < 8; _direction = _direction + 1) { + _candidate = DAT_TileMapState::instance.directionTranslationMatrix[_y][_direction] + _tile; + if (DAT_TileMapState::instance.WalkLayer[_candidate] != this->searchGeneration + && (area == (int)(short)DAT_TileMapState::instance.PathConnectionLayer[_candidate] + || (iVar2 = MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func:: + calculateCanPlayerUnitsNavigateToAreaFromArea, + DAT_PathFindingState::ptr)(playerID, (dword)((int)(area)), + (dword)((int)(( + int)(short)DAT_TileMapState::instance.PathConnectionLayer[_candidate])), + 0), + iVar2 != 0))) { + /* + queue tiles in area that are navigatible by this player without climbing + */ + short sVar1 + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction] + .short_.xOffset; + this->searchQueue.xQueue[this->searchQueue.writeIndex] = sVar1 + _x; + DAT_TileMapState::instance.WalkLayer[_candidate] = (short)this->searchGeneration; + DAT_TileMapState::instance.CertainPathLayer[_candidate] + = (short)this->searchQueue.currentDistance + 1; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction] + .short_.yOffset + + _y; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = _candidate; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + } + + this->searchQueue.readIndex = this->searchQueue.readIndex + 1; + if (0x13a10 <= (int)this->searchQueue.readIndex) { + this->searchQueue.readIndex = 0; + } + if (this->searchQueue.readIndex == this->searchQueue.writeIndex) + break; + } + } + this->searchQueue.readIndex = 0; + if (0 < (int)this->searchQueue.writeIndex) { + piVar3 = &this->searchQueue.destinationsArray[0].tile2OrAHelper; + do { + _tile2 = this->searchQueue.tilesQueue[this->searchQueue.readIndex]; + /* + no wall tower gatehouse crenel nor keep + */ + if ((DAT_TileMapState::instance.LogicLayer[_tile2] & 0x10000300U) == 0) { + pXVar4 = DAT_ClimbLogicDefinedData::instance.CardinalHorizontalFirstSearchOrder; + do { + int _candidate2 = DAT_ViewportRenderState::instance + .translationMatrix[pXVar4->y + + (int)this->searchQueue.yQueue[this->searchQueue.readIndex]] + .addXgetTile + + pXVar4->x + (int)this->searchQueue.xQueue[this->searchQueue.readIndex]; + if ((DAT_TileMapState::instance.LogicLayer[_candidate2] & 0x300U) != 0 + && (DAT_TileMapState::instance.LogicLayer[_candidate2] & 0x400000U) == 0 + && (DAT_TileMapState::instance.WallOwnerLayer[_candidate2] & 7) + 1 != playerID) { + /* + candidate 2 is wall tower gatehouse, or crenel (variation) + */ + if (_candidate2 != 0) { + *piVar3 = _candidate2; + _dIndex = _dIndex + 1; + ((PathHelper12*)(piVar3 + -1))->tile1 = _tile2; + piVar3 = piVar3 + 3; + if (_dIndex >= maxDestinations) { + return; + } + this->searchQueue.tilesQueue[this->searchQueue.readIndex] = -1; + } + break; + } + pXVar4 = pXVar4 + 1; + } while ((int)pXVar4 + < (int)&DAT_ClimbLogicDefinedData::instance.CardinalHorizontalFirstSearchOrder[4]); + } + this->searchQueue.readIndex = this->searchQueue.readIndex + 1; + } while ((int)this->searchQueue.readIndex < (int)this->searchQueue.writeIndex); + } + this->searchQueue.readIndex = 0; + if (0 < (int)this->searchQueue.writeIndex) { + piVar3 = &((PathFindingStatePartB*)(this->climbData + 200))->destinationsArray[_dIndex].tile2OrAHelper; + do { + iVar2 = this->searchQueue.tilesQueue[this->searchQueue.readIndex]; + /* + no wall tower gatehouse crenel nor keep + */ + if ((DAT_TileMapState::instance.LogicLayer[iVar2] & 0x10000300U) == 0 && iVar2 != -1) { + ((PathHelper12*)(piVar3 + -1))->tile1 = iVar2; + *piVar3 = 0; + _dIndex = _dIndex + 1; + piVar3 = piVar3 + 3; + if (_dIndex >= maxDestinations) { + return; + } + } + this->searchQueue.readIndex = this->searchQueue.readIndex + 1; + } while ((int)this->searchQueue.readIndex < (int)this->searchQueue.writeIndex); + } + this->searchQueue.destinationsArray[_dIndex].tile1 = 0; + ((PathFindingStatePartB*)(this->climbData + 200))->destinationsArray[_dIndex].tile2OrAHelper = 0; + return; + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/raiseLand2.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/raiseLand2.cpp new file mode 100644 index 0000000000..fc484975e5 --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/raiseLand2.cpp @@ -0,0 +1,151 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/IO/LowLevelMemory.func.hpp" +#include "OpenSHC/Map/TileMapState.func.hpp" +#include "OpenSHC/Map/Location/Point8ShortXY.hpp" + +#include "OpenSHC/Globals/DAT_LowLevelMemory.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + using OpenSHC::Map::Location::Point8ShortXY; + + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x0049A6D0 + void PathFindingState::raiseLand2(uint x, uint y, int maxDistance) + { + if (x > 399 || y > 399) { + return; + } + if (DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[y * 400 + x] == '\0') { + return; + } + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 160800, '\0', (void*)((int)(DAT_TileMapState::instance.CertainPathLayer))); + this->searchQueue.readIndex = 0; + this->searchQueue.writeIndex = 1; + this->searchQueue.currentDistance = 1; + this->searchQueue.yQueue[0] = (short)y; + this->searchQueue.xQueue[0] = (short)x; + this->searchQueue.tilesQueue[0] = DAT_ViewportRenderState::instance.translationMatrix[y].addXgetTile + x; + DAT_TileMapState::instance.CertainPathLayer[this->searchQueue.tilesQueue[0]] = 1; + int uVar1 = DAT_TileMapState::instance.PathConnectionLayer[this->searchQueue.tilesQueue[0]]; + if (this->searchQueue.readIndex != this->searchQueue.writeIndex) { + do { + uint tile = this->searchQueue.tilesQueue[this->searchQueue.readIndex]; + if (0x13a0f < tile) + break; + int sVar2 = (int)this->searchQueue.xQueue[this->searchQueue.readIndex]; + int sVar3 = (int)this->searchQueue.yQueue[this->searchQueue.readIndex]; + this->searchQueue.currentDistance = (int)DAT_TileMapState::instance.CertainPathLayer[tile]; + if ((int)this->searchQueue.currentDistance > maxDistance) + break; + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::raiseLand, DAT_TileMapState::ptr)( + tile, (uint)(sVar3), 4, 1); + for (int _direction = 0; _direction < 8; _direction = _direction + 4) { + int iVar5 = DAT_TileMapState::instance.directionTranslationMatrix[sVar3][_direction] + tile; + if (DAT_TileMapState::instance.CertainPathLayer[iVar5] < 1 + && (short)DAT_TileMapState::instance.PathConnectionLayer[iVar5] == uVar1 + && (DAT_TileMapState::instance.LogicLayer[iVar5] & 0x30) == 0) { + DAT_TileMapState::instance.CertainPathLayer[iVar5] + = (short)this->searchQueue.currentDistance + 1; + this->searchQueue.xQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction] + .short_.xOffset + + sVar2; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction] + .short_.yOffset + + sVar3; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = iVar5; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + iVar5 = DAT_TileMapState::instance.directionTranslationMatrix[sVar3][_direction + 1] + tile; + if (DAT_TileMapState::instance.CertainPathLayer[iVar5] < 1 + && (short)DAT_TileMapState::instance.PathConnectionLayer[iVar5] == uVar1 + && (DAT_TileMapState::instance.LogicLayer[iVar5] & 0x30) == 0) { + DAT_TileMapState::instance.CertainPathLayer[iVar5] + = (short)this->searchQueue.currentDistance + 1; + this->searchQueue.xQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction + 1] + .short_.xOffset + + sVar2; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction + 1] + .short_.yOffset + + sVar3; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = iVar5; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + iVar5 = DAT_TileMapState::instance.directionTranslationMatrix[sVar3][_direction + 2] + tile; + if (DAT_TileMapState::instance.CertainPathLayer[iVar5] < 1 + && (short)DAT_TileMapState::instance.PathConnectionLayer[iVar5] == uVar1 + && (DAT_TileMapState::instance.LogicLayer[iVar5] & 0x30) == 0) { + DAT_TileMapState::instance.CertainPathLayer[iVar5] + = (short)this->searchQueue.currentDistance + 1; + this->searchQueue.xQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction + 2] + .short_.xOffset + + sVar2; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction + 2] + .short_.yOffset + + sVar3; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = iVar5; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + iVar5 = DAT_TileMapState::instance.directionTranslationMatrix[sVar3][_direction + 3] + tile; + if (DAT_TileMapState::instance.CertainPathLayer[iVar5] < 1 + && (short)DAT_TileMapState::instance.PathConnectionLayer[iVar5] == uVar1 + && (DAT_TileMapState::instance.LogicLayer[iVar5] & 0x30) == 0) { + DAT_TileMapState::instance.CertainPathLayer[iVar5] + = (short)this->searchQueue.currentDistance + 1; + this->searchQueue.xQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction + 3] + .short_.xOffset + + sVar2; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction + 3] + .short_.yOffset + + sVar3; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = iVar5; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + } + + this->searchQueue.readIndex = this->searchQueue.readIndex + 1; + if (0x13a10 <= (int)this->searchQueue.readIndex) { + this->searchQueue.readIndex = 0; + } + } while (this->searchQueue.readIndex != this->searchQueue.writeIndex); + } + DAT_TileMapState::instance.forceUpdateLogicalAndMiscDisplayLayers = 1; + DAT_TileMapState::instance.forceUpdateTextureTilemap = 1; + DAT_TileMapState::instance.forceUpdateGFXLayers = 1; + return; + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/recomputeALGPathFindingTileMapUnk.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/recomputeALGPathFindingTileMapUnk.cpp new file mode 100644 index 0000000000..ad6792f7cb --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/recomputeALGPathFindingTileMapUnk.cpp @@ -0,0 +1,179 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/IO/LowLevelMemory.func.hpp" + +#include "OpenSHC/Globals/DAT_LowLevelMemory.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x0049E510 + void PathFindingState::recomputeALGPathFindingTileMapUnk(int someMax, uint x, uint y, undefined4 param_4) + { + uint uVar3; + int iVar4; + if (x > 399 || y > 399) { + return; + } + if (DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[y * 400 + x] == '\0') { + return; + } + this->searchGeneration = this->searchGeneration + 1; + if (32000 < this->searchGeneration) { + this->searchGeneration = 1; + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 160800, '\0', (void*)((int)(DAT_TileMapState::instance.WalkLayer))); + } + this->searchQueue.currentDistance = 1; + this->searchQueue.readIndex = 0; + this->searchQueue.writeIndex = 1; + this->searchQueue.yQueue[0] = (short)y; + this->searchQueue.xQueue[0] = (short)x; + this->searchQueue.tilesQueue[0] = DAT_ViewportRenderState::instance.translationMatrix[y].addXgetTile + x; + if ((DAT_TileMapState::instance.AIInfoLayer[this->searchQueue.tilesQueue[0]] & 0xf) == 0) { + DAT_TileMapState::instance.CertainPathLayer[this->searchQueue.tilesQueue[0]] = 1; + DAT_TileMapState::instance.WalkLayer[this->searchQueue.tilesQueue[0]] = (short)this->searchGeneration; + if (this->searchQueue.readIndex != this->searchQueue.writeIndex) { + while (uVar3 = this->searchQueue.tilesQueue[this->searchQueue.readIndex], uVar3 <= 0x13a0f) { + DAT_TileMapState::instance.AIInfoLayer[uVar3] + = DAT_TileMapState::instance.AIInfoLayer[uVar3] | (byte)param_4; + int sVar1 = (int)this->searchQueue.xQueue[this->searchQueue.readIndex]; + int sVar2 = (int)this->searchQueue.yQueue[this->searchQueue.readIndex]; + this->searchQueue.currentDistance = (int)DAT_TileMapState::instance.CertainPathLayer[uVar3]; + if (0x13a10 < (int)this->searchQueue.currentDistance) { + return; + } + if ((int)this->searchQueue.currentDistance > someMax) { + return; + } + for (int _direction = 0; _direction < 8; _direction = _direction + 4) { + if ((DAT_TileMapState::instance.LogicLayer[uVar3] & 0x30U) == 0 + && ((byte)param_4 != 8 + || ((DAT_TileMapState::instance.LogicLayer[uVar3] & 0x6a5014b1U) == 0)) + && (iVar4 + = DAT_TileMapState::instance.directionTranslationMatrix[sVar2][_direction] + uVar3, + DAT_TileMapState::instance.WalkLayer[iVar4] != this->searchGeneration) + && ((byte)param_4 == 0x80 || (DAT_TileMapState::instance.AIInfoLayer[iVar4] == '\0'))) { + DAT_TileMapState::instance.CertainPathLayer[iVar4] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[iVar4] = (short)this->searchGeneration; + this->searchQueue.xQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction] + .short_.xOffset + + sVar1; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction] + .short_.yOffset + + sVar2; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = iVar4; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + if ((DAT_TileMapState::instance.LogicLayer[uVar3] & 0x30U) == 0 + && ((byte)param_4 != 8 + || ((DAT_TileMapState::instance.LogicLayer[uVar3] & 0x6a5014b1U) == 0)) + && (iVar4 = DAT_TileMapState::instance.directionTranslationMatrix[sVar2][_direction + 1] + + uVar3, + DAT_TileMapState::instance.WalkLayer[iVar4] != this->searchGeneration) + && ((byte)param_4 == 0x80 || (DAT_TileMapState::instance.AIInfoLayer[iVar4] == '\0'))) { + DAT_TileMapState::instance.CertainPathLayer[iVar4] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[iVar4] = (short)this->searchGeneration; + this->searchQueue.xQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance + .clockwiseCardinalTranslationMatrix[_direction + 1] + .short_.xOffset + + sVar1; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance + .clockwiseCardinalTranslationMatrix[_direction + 1] + .short_.yOffset + + sVar2; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = iVar4; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + if ((DAT_TileMapState::instance.LogicLayer[uVar3] & 0x30U) == 0 + && ((byte)param_4 != 8 + || ((DAT_TileMapState::instance.LogicLayer[uVar3] & 0x6a5014b1U) == 0)) + && (iVar4 = DAT_TileMapState::instance.directionTranslationMatrix[sVar2][_direction + 2] + + uVar3, + DAT_TileMapState::instance.WalkLayer[iVar4] != this->searchGeneration + && (((byte)param_4 == 0x80 + || (DAT_TileMapState::instance.AIInfoLayer[iVar4] == '\0'))))) { + DAT_TileMapState::instance.CertainPathLayer[iVar4] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[iVar4] = (short)this->searchGeneration; + this->searchQueue.xQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance + .clockwiseCardinalTranslationMatrix[_direction + 2] + .short_.xOffset + + sVar1; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance + .clockwiseCardinalTranslationMatrix[_direction + 2] + .short_.yOffset + + sVar2; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = iVar4; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + if ((DAT_TileMapState::instance.LogicLayer[uVar3] & 0x30U) == 0 + && ((byte)param_4 != 8 + || ((DAT_TileMapState::instance.LogicLayer[uVar3] & 0x6a5014b1U) == 0)) + && (iVar4 = DAT_TileMapState::instance.directionTranslationMatrix[sVar2][_direction + 3] + + uVar3, + DAT_TileMapState::instance.WalkLayer[iVar4] != this->searchGeneration) + && ((byte)param_4 == 0x80 || (DAT_TileMapState::instance.AIInfoLayer[iVar4] == '\0'))) { + DAT_TileMapState::instance.CertainPathLayer[iVar4] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[iVar4] = (short)this->searchGeneration; + this->searchQueue.xQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance + .clockwiseCardinalTranslationMatrix[_direction + 3] + .short_.xOffset + + sVar1; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance + .clockwiseCardinalTranslationMatrix[_direction + 3] + .short_.yOffset + + sVar2; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = iVar4; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + } + this->searchQueue.readIndex = this->searchQueue.readIndex + 1; + if (0x13a10 <= (int)this->searchQueue.readIndex) { + this->searchQueue.readIndex = 0; + } + if (this->searchQueue.readIndex == this->searchQueue.writeIndex) { + return; + } + } + } + } + return; + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/recountUnitsUsingClimbData.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/recountUnitsUsingClimbData.cpp new file mode 100644 index 0000000000..d0f49a0cca --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/recountUnitsUsingClimbData.cpp @@ -0,0 +1,58 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/Map/Units/UnitLogicState.hpp" + +#include "OpenSHC/Globals/DAT_UnitsState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + + using OpenSHC::Map::Units::UnitLogicState; + + /* + decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x004A4BB0 + void PathFindingState::recountUnitsUsingClimbData(int climbDataID) + { + int* _ptrUnitID; + int _counter; + int _canBeUsed; + int* _ptrUnitUID; + int _unitID; + OpenSHC::Map::ClimbData* _climb; + _counter = 0; + _climb = &this->climbData[climbDataID]; + _canBeUsed = _climb->canBeUsed; + _climb->numberOfUnitsUsing = 0; + if (_canBeUsed != 0) { + _ptrUnitID = &this->climbData[climbDataID].unitID1; + do { + _unitID = *_ptrUnitID; + if (_unitID != 0) { + int _uid = (&this->climbData[climbDataID].unitUID1)[_counter]; + _ptrUnitUID = &this->climbData[climbDataID].unitUID1 + _counter; + if (DAT_UnitsState::instance.units[_unitID].logicalState != OpenSHC::Map::Units::ULS_NORMAL) { + *_ptrUnitID = 0; + *_ptrUnitUID = 0; + } else if (DAT_UnitsState::instance.units[_unitID].uid != _uid) { + *_ptrUnitID = 0; + *_ptrUnitUID = 0; + } else if (DAT_UnitsState::instance.units[_unitID].climbDataID != climbDataID) { + *_ptrUnitID = 0; + *_ptrUnitUID = 0; + } else { + _climb->numberOfUnitsUsing = _climb->numberOfUnitsUsing + 1; + } + } + _ptrUnitID = _ptrUnitID + 1; + _counter = _counter + 1; + } while (_counter < 50); + } + return; + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/registerUnitOnClimbData.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/registerUnitOnClimbData.cpp new file mode 100644 index 0000000000..df7c68351d --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/registerUnitOnClimbData.cpp @@ -0,0 +1,54 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/Globals/DAT_UnitsState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + + /* + Attempts to register unit param_2 on climb data slot param_1. Returns 0 if the climb system is disabled + (field63_0xc0 == 0), -1 if the slot is unusable or already at capacity (50 units), or 1 on success. On + success increments numberOfUnitsUsing, stores the unit ID and UID in the first free slot, and copies + climbDataRelated to the unit (zeroed for climb types 3, 4, and 5). renamed by: Claude Sonnet 4.6 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x004A4C70 + undefined4 PathFindingState::registerUnitOnClimbData(int param_1, int param_2) + { + int iVar1; + int* piVar2; + if (this->field63_0xc0 == 0) { + return (undefined4)(0); + } + if ((this->climbData[param_1].canBeUsed != 0) + && (iVar1 = this->climbData[param_1].numberOfUnitsUsing, iVar1 < 0x32)) { + this->climbData[param_1].numberOfUnitsUsing = iVar1 + 1; + DAT_UnitsState::instance.units[param_2].climbDataRelated = this->climbData[param_1].climbDataRelated; + if (this->climbData[param_1].type == 3) { + DAT_UnitsState::instance.units[param_2].climbDataRelated = 0; + } + if (this->climbData[param_1].type == 4) { + DAT_UnitsState::instance.units[param_2].climbDataRelated = 0; + } + if (this->climbData[param_1].type == 5) { + DAT_UnitsState::instance.units[param_2].climbDataRelated = 0; + } + iVar1 = 0; + piVar2 = &this->climbData[param_1].unitID1; + do { + if (*piVar2 == 0) { + (&this->climbData[param_1].unitID1)[iVar1] = param_2; + (&this->climbData[param_1].unitUID1)[iVar1] = DAT_UnitsState::instance.units[param_2].uid; + return (undefined4)(1); + } + iVar1 = iVar1 + 1; + piVar2 = piVar2 + 1; + } while (iVar1 < 0x32); + return (undefined4)(1); + } + return (undefined4)(0xffffffff); + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/reverseCurrentPathPlan.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/reverseCurrentPathPlan.cpp new file mode 100644 index 0000000000..810511cb46 --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/reverseCurrentPathPlan.cpp @@ -0,0 +1,130 @@ +#include "../PathFindingState.func.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + + /* + decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x0049A5E0 + void PathFindingState::reverseCurrentPathPlan() + { + int bVar1; + int bVar2; + /* + Index from start of path + */ + uint _index = 0; + /* + === ONLY REVERSE IF PATH HAS MORE THAN 1 ELEMENT === + */ + /* + Index from end of path + */ + if (1 < (int)this->searchQueue.pathPlanIndex) { + /* + Calculate number of swaps needed (swap pairs from both ends toward center) Example: 8 elements = 4 + swaps, 7 elements = 3 swaps + */ + int _swapCounter = (this->searchQueue.pathPlanIndex - 2 >> 1) + 1; + uint _endIndex = this->searchQueue.pathPlanIndex; + do { + /* + === SWAP LOOP: Exchange elements from both ends === === EXTRACT DIRECTION AT START (uVar3) === + */ + _endIndex = _endIndex - 1; + if ((_index & 1) == 0) { + /* + Even index: direction is in LOW nibble (bits 0-3) + */ + bVar2 = this->searchQueue.ptrPathPlan[(int)_index / 2] & 0xf; + } else { + /* + Odd index: direction is in HIGH nibble (bits 4-7) + */ + bVar2 = (char)this->searchQueue.ptrPathPlan[(int)_index / 2] >> 4; + } + /* + === EXTRACT DIRECTION AT END (_prevIndex) === + */ + if ((_endIndex & 1) == 0) { + /* + Even index: direction is in LOW nibble + */ + bVar1 = this->searchQueue.ptrPathPlan[(int)_endIndex / 2] & 0xf; + } else { + /* + Odd index: direction is in HIGH nibble + */ + bVar1 = (char)this->searchQueue.ptrPathPlan[(int)_endIndex / 2] >> 4; + } + /* + === WRITE END DIRECTION TO START POSITION === + */ + if ((_index & 1) == 0) { + /* + Even index: clear LOW nibble, keep HIGH nibble + */ + this->searchQueue.ptrPathPlan[(int)_index / 2] + = this->searchQueue.ptrPathPlan[(int)_index / 2] & 0xf0; + } else { + /* + Odd index: clear HIGH nibble, keep LOW nibble + */ + this->searchQueue.ptrPathPlan[(int)_index / 2] + = this->searchQueue.ptrPathPlan[(int)_index / 2] & 0xf; + /* + Shift value to HIGH nibble position + */ + bVar1 = bVar1 << 4; + } + /* + Write the direction value + */ + this->searchQueue.ptrPathPlan[(int)_index / 2] + = this->searchQueue.ptrPathPlan[(int)_index / 2] + bVar1; + /* + === WRITE START DIRECTION TO END POSITION === + */ + if ((_endIndex & 1) == 0) { + /* + Even index: clear LOW nibble + */ + this->searchQueue.ptrPathPlan[(int)_endIndex / 2] + = this->searchQueue.ptrPathPlan[(int)_endIndex / 2] & 0xf0; + } else { + /* + Odd index: clear HIGH nibble + */ + this->searchQueue.ptrPathPlan[(int)_endIndex / 2] + = this->searchQueue.ptrPathPlan[(int)_endIndex / 2] & 0xf; + /* + Shift value to HIGH nibble position + */ + bVar2 = bVar2 << 4; + } + /* + Write the direction value + */ + this->searchQueue.ptrPathPlan[(int)_endIndex / 2] + = this->searchQueue.ptrPathPlan[(int)_endIndex / 2] + bVar2; + /* + === MOVE INDICES TOWARD CENTER === Move end index forward + */ + /* + Move start index forward + */ + _index = _index + 1; + /* + Decrement swap counter + */ + _swapCounter = _swapCounter + -1; + } while (_swapCounter != 0); + } + return; + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/setChangedLayerZeroBasedOn40x40Layer.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/setChangedLayerZeroBasedOn40x40Layer.cpp new file mode 100644 index 0000000000..661086ffbc --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/setChangedLayerZeroBasedOn40x40Layer.cpp @@ -0,0 +1,149 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x0049AF50 + void PathFindingState::setChangedLayerZeroBasedOn40x40Layer(uint flag_and_offset) + { + if ((this->field10_0x28 == 0) && (flag_and_offset == 0)) { + int _row = DAT_TileMapState::instance.someIndex; + if (_row <= (int)DAT_TileMapState::instance.someLimit) { + int _index10 = _row * 10; + /* + 10 400x400 rows + */ + int _index4000 = _row * 4000; + int _someX = _row * 120; + byte* _pMap4040 = DAT_TileMapState::instance.mapping40x40[_row]; + do { + int _someYLikeLimit = DAT_TileMapState::instance.someYLikeLimit; + int _someY = DAT_TileMapState::instance.someYLike; + if (_someY <= _someYLikeLimit) { + flag_and_offset = _someY * 10 + 1; + do { + if (_pMap4040[_someY] != '\0') { + /* + update this part + */ + _pMap4040[_someY] = 0; + int _cur10 = 0; + int _yOffset = _index4000; + int _curX = _someX; + do { + uint _coord2 = _index10 + _cur10; + int local_1c = 2; + uint _x = flag_and_offset; + do { + if (_x - 1 <= 399 && _coord2 <= 399 + && DAT_ViewportRenderState::instance + .DAT_BinaryTileMap400x400[_yOffset + (_x - 1)] + != '\0') { + /* + set changed layer to 0 + */ + /* + is valid coordinate + */ + DAT_TileMapState::instance + .ChangedLayer[*(int*)((int)&DAT_ViewportRenderState::instance + .translationMatrix[0] + .addXgetTile + + _curX) + + (_x - 1)] = 0; + } + if (_x <= 399 && _coord2 <= 399 + && DAT_ViewportRenderState::instance + .DAT_BinaryTileMap400x400[_yOffset + _x] + != '\0') { + DAT_TileMapState::instance + .ChangedLayer[*(int*)((int)&DAT_ViewportRenderState::instance + .translationMatrix[0] + .addXgetTile + + _curX) + + _x] = 0; + } + if (_x + 1 <= 399 && _coord2 <= 399 + && DAT_ViewportRenderState::instance + .DAT_BinaryTileMap400x400[_yOffset + _x + 1] + != '\0') { + DAT_TileMapState::instance + .ChangedLayer[*(int*)((int)&DAT_ViewportRenderState::instance + .translationMatrix[0] + .addXgetTile + + _curX) + + (_x + 1)] = 0; + } + if (_x + 2 <= 399 && _coord2 <= 399 + && DAT_ViewportRenderState::instance + .DAT_BinaryTileMap400x400[_yOffset + _x + 2] + != '\0') { + DAT_TileMapState::instance + .ChangedLayer[*(int*)((int)&DAT_ViewportRenderState::instance + .translationMatrix[0] + .addXgetTile + + _curX) + + (_x + 2)] = 0; + } + if (_x + 3 <= 399 && _coord2 <= 399 + && DAT_ViewportRenderState::instance + .DAT_BinaryTileMap400x400[_yOffset + _x + 3] + != '\0') { + DAT_TileMapState::instance + .ChangedLayer[*(int*)((int)&DAT_ViewportRenderState::instance + .translationMatrix[0] + .addXgetTile + + _curX) + + (_x + 3)] = 0; + } + _x = _x + 5; + local_1c = local_1c + -1; + } while (local_1c != 0); + _cur10 = _cur10 + 1; + _curX = _curX + 0xc; + _yOffset = _yOffset + 400; + } while (_cur10 < 10); + _someYLikeLimit = DAT_TileMapState::instance.someYLikeLimit; + } + flag_and_offset = flag_and_offset + 10; + _someY = _someY + 1; + } while (_someY <= _someYLikeLimit); + } + _index4000 = _index4000 + 4000; + _index10 = _index10 + 10; + _row = _row + 1; + _pMap4040 = _pMap4040 + 40; + _someX = _someX + 120; + } while (_row <= (int)DAT_TileMapState::instance.someLimit); + } + this->mappingYRelated = 1000; + this->yLimit = 0; + DAT_TileMapState::instance.someIndex = 1000; + DAT_TileMapState::instance.someLimit = 0; + DAT_TileMapState::instance.someYLike = 1000; + DAT_TileMapState::instance.someYLikeLimit = 0; + return; + } + this->field10_0x28 = 0; + this->mappingYRelated = 0; + this->yLimit = 399; + DAT_TileMapState::instance.someIndex = 0; + DAT_TileMapState::instance.someLimit = 39; + DAT_TileMapState::instance.someYLike = 0; + DAT_TileMapState::instance.someYLikeLimit = 0x27; + return; + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/setClimbBasedOnClosestClimbData.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/setClimbBasedOnClosestClimbData.cpp new file mode 100644 index 0000000000..f415bb2231 --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/setClimbBasedOnClosestClimbData.cpp @@ -0,0 +1,113 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/Map/Navigation/DirectionAlgorithmState.func.hpp" +#include "OpenSHC/Map/Units/UnitsState.func.hpp" + +#include "OpenSHC/Globals/DAT_DirectionAlgorithmState.hpp" +#include "OpenSHC/Globals/DAT_UnitsState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + + /* + called when pathfinding with walls decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x004A4930 + int PathFindingState::setClimbBasedOnClosestClimbData(int unitID, int ladderWallGroup, int ladderArea) + { + int iVar1; + int fromXPosition; + ClimbData* _pClimbData; + ClimbData* _pClimbData2; + int _downOrUp1; + int _climbDataID; + int _climbData2; + int _minDistance; + int _downOrUp; + int _distance; + _minDistance = 1000; + _climbData2 = 0; + _downOrUp = 0; + if (this->field63_0xc0 == 0) { + return 200; + } + int _climbDataCounter = 1; + if (1 < this->maxClimbDataCount) { + _pClimbData = &this->climbData[1]; + _downOrUp = 0; + do { + if ((_pClimbData->canBeUsed == 1) && (_pClimbData->isRecognizedByPathfinding != 0)) { + iVar1 = MACRO_CALL_MEMBER( + OpenSHC::Map::Units::UnitsState_Func::checkUnitHasPropertyBasedOnUnitType, + DAT_UnitsState::ptr)(unitID, _pClimbData->type); + if ((iVar1 != 0) && (_pClimbData->type == 1)) { + if (_pClimbData->area == ladderWallGroup) { + _downOrUp1 = 0; + if (_pClimbData->wallGroupAreaID == ladderArea) { + iVar1 = _pClimbData->bottomYPosition; + fromXPosition = _pClimbData->bottomXPosition; + LAB_004a49e1: + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::DirectionAlgorithmState_Func:: + setAxisBasedDistanceResult, + DAT_DirectionAlgorithmState::ptr)((int)DAT_UnitsState::instance.units[unitID].x, + (int)(DAT_UnitsState::instance.units[unitID].y), fromXPosition, iVar1); + _distance = DAT_DirectionAlgorithmState::instance.distanceHigh + + _pClimbData->numberOfUnitsUsing * 8; + if (_distance < _minDistance) { + _downOrUp = _downOrUp1; + _minDistance = _distance; + _climbData2 = _climbDataCounter; + if (_downOrUp1 == 0) { + this->climbX = _pClimbData->bottomXPosition; + this->climbY = _pClimbData->bottomYPosition; + } else { + this->climbX = _pClimbData->topXPosition; + this->climbY = _pClimbData->topYPosition; + } + } + } + } else if ((_pClimbData->area == ladderArea) + && (_downOrUp1 = 1, _pClimbData->wallGroupAreaID == ladderWallGroup)) { + iVar1 = _pClimbData->topYPosition; + fromXPosition = _pClimbData->topXPosition; + goto LAB_004a49e1; + } + } + } + _climbDataCounter = _climbDataCounter + 1; + _pClimbData = _pClimbData + 1; + } while (_climbDataCounter < this->maxClimbDataCount); + } + DAT_UnitsState::instance.units[unitID].climbDirection = _downOrUp; + if (_climbData2 == 0) { + _pClimbData2 = &this->climbData[1]; + _climbDataID = 1; + do { + if ((_pClimbData2->canBeUsed == 1) && (_pClimbData2->isRecognizedByPathfinding != 0)) { + iVar1 = MACRO_CALL_MEMBER( + OpenSHC::Map::Units::UnitsState_Func::checkUnitHasPropertyBasedOnUnitType, + DAT_UnitsState::ptr)(unitID, _pClimbData2->type); + if ((iVar1 != 0) && (0 < _pClimbData2->buildingArea)) { + if (_pClimbData2->area == ladderArea) { + this->climbX = this->climbData[_climbDataID].bottomXPosition; + this->climbY = this->climbData[_climbDataID].bottomYPosition; + return _climbDataID; + } + if (_pClimbData2->wallGroupAreaID == ladderArea) { + this->climbX = this->climbData[_climbDataID].topXPosition; + this->climbY = this->climbData[_climbDataID].topYPosition; + return _climbDataID; + } + } + } + _climbDataID = _climbDataID + 1; + _pClimbData2 = _pClimbData2 + 1; + } while (_climbDataID < 200); + } + return _climbData2; + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/setDestinationPairsBasedOnPreviousSearch.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/setDestinationPairsBasedOnPreviousSearch.cpp new file mode 100644 index 0000000000..45c87ffe9d --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/setDestinationPairsBasedOnPreviousSearch.cpp @@ -0,0 +1,56 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" + +#include "OpenSHC/Globals/DAT_GameState.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x004A65E0 + void PathFindingState::setDestinationPairsBasedOnPreviousSearch(int playerIDMin1, int attackedPlayerID) + { + int _pair = 0; + this->searchQueue.readIndex = 0; + if (this->searchQueue.writeIndex != 0) { + do { + uint y = (uint)this->searchQueue.yQueue[this->searchQueue.readIndex]; + int _tile = this->searchQueue.tilesQueue[this->searchQueue.readIndex]; + uint x = _tile - DAT_ViewportRenderState::instance.translationMatrix[y].addXgetTile; + uint _attackedDistance + = (uint)DAT_TileMapState::instance.SEC_PathfindingCostTileMap1105[attackedPlayerID][_tile]; + if (DAT_TileMapState::instance.WalkLayer[_tile] == this->searchGeneration && _attackedDistance != 0 + && _attackedDistance - 4294967224 < 4 + && DAT_TileMapState::instance.CertainPathLayer[_tile] < 0x4c + && DAT_TileMapState::instance.CertainPathLayer[_tile] != 100) { + MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::PathFindingState_Func::budgetFloodFillOnCertainPathLayer, this)( + x, y, (int)(100), (int)(50)); + DAT_GameState::instance.mapAndTime.unitMoveDestinationXYPairs[playerIDMin1][_pair].x = x; + DAT_GameState::instance.mapAndTime.unitMoveDestinationXYPairs[playerIDMin1][_pair].y = y; + _pair = _pair + 1; + } + if (_pair >= 40) { + return; + } + this->searchQueue.readIndex = this->searchQueue.readIndex + 1; + if (0x13a10 <= (int)this->searchQueue.readIndex) { + this->searchQueue.readIndex = 0; + } + } while (this->searchQueue.readIndex != this->searchQueue.writeIndex); + } + return; + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/setMoveDestinationPairs.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/setMoveDestinationPairs.cpp new file mode 100644 index 0000000000..525749dc9e --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/setMoveDestinationPairs.cpp @@ -0,0 +1,57 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" + +#include "OpenSHC/Globals/DAT_GameState.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x004A66D0 + void PathFindingState::setMoveDestinationPairs(int playerIDmin1, int playerID, int maxCost) + { + int iVar1 = 0; + if (100 < maxCost) { + maxCost = 100; + } + this->searchQueue.readIndex = 0; + if (this->searchQueue.writeIndex != 0) { + do { + uint _y = (uint)this->searchQueue.yQueue[this->searchQueue.readIndex]; + int _tileCandidate = this->searchQueue.tilesQueue[this->searchQueue.readIndex]; + uint _x = _tileCandidate - DAT_ViewportRenderState::instance.translationMatrix[_y].addXgetTile; + uint _cost + = (uint)DAT_TileMapState::instance.SEC_PathfindingCostTileMap1105[playerID][_tileCandidate]; + if (_cost != 0 && (int)_cost >= maxCost && (int)_cost <= maxCost + 10 + && DAT_TileMapState::instance.CertainPathLayer[_tileCandidate] != 100) { + MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::PathFindingState_Func::budgetFloodFillOnCertainPathLayer, this)( + _x, _y, 100, 200); + DAT_GameState::instance.mapAndTime.unitMoveDestinationXYPairs[playerIDmin1][iVar1].x = _x; + DAT_GameState::instance.mapAndTime.unitMoveDestinationXYPairs[playerIDmin1][iVar1].y = _y; + iVar1 = iVar1 + 1; + } + if (0x13 < iVar1) { + return; + } + this->searchQueue.readIndex = this->searchQueue.readIndex + 1; + if (0x13a10 <= (int)this->searchQueue.readIndex) { + this->searchQueue.readIndex = 0; + } + } while (this->searchQueue.readIndex != this->searchQueue.writeIndex); + } + return; + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/setWalkabilityBorderLogicLayerForSmallerMapSizes.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/setWalkabilityBorderLogicLayerForSmallerMapSizes.cpp new file mode 100644 index 0000000000..2aeeb53c78 --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/setWalkabilityBorderLogicLayerForSmallerMapSizes.cpp @@ -0,0 +1,154 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/IO/LowLevelMemory.func.hpp" +#include "OpenSHC/Map/Location/Point8ShortXY.hpp" + +#include "OpenSHC/Globals/DAT_LowLevelMemory.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + using OpenSHC::Map::Location::Point8ShortXY; + + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + Executes a flood file with logic layer 0x10 to indicate impenetrable land decompilerscript: committed: + 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x004A0E50 + void PathFindingState::setWalkabilityBorderLogicLayerForSmallerMapSizes() + { + short sVar3; + this->searchGeneration = this->searchGeneration + 1; + this->resultTile = 0; + this->resultY = 0; + this->resultX = 0; + if (32000 < this->searchGeneration) { + this->searchGeneration = 1; + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 160800, '\0', (void*)((int)(DAT_TileMapState::instance.WalkLayer))); + } + this->searchQueue.readIndex = 0; + this->searchQueue.writeIndex = 1; + this->searchQueue.currentDistance = 1; + this->searchQueue.yQueue[0] = 2; + this->searchQueue.xQueue[0] = 198; + int _startTile = DAT_ViewportRenderState::instance.translationMatrix[2].addXgetTile + 0xc6; + this->searchQueue.tilesQueue[0] = _startTile; + DAT_TileMapState::instance.CertainPathLayer[_startTile] = (short)this->searchQueue.currentDistance; + DAT_TileMapState::instance.WalkLayer[this->searchQueue.tilesQueue[0]] = (short)this->searchGeneration; + while (this->searchQueue.readIndex != this->searchQueue.writeIndex) { + uint uVar4 = this->searchQueue.tilesQueue[this->searchQueue.readIndex]; + if (0x13a0f < uVar4) { + return; + } + int sVar1 = (int)this->searchQueue.yQueue[this->searchQueue.readIndex]; + int sVar2 = (int)this->searchQueue.xQueue[this->searchQueue.readIndex]; + this->searchQueue.currentDistance = (int)DAT_TileMapState::instance.CertainPathLayer[uVar4]; + for (int _direction = 0; _direction < 8; _direction = _direction + 4) { + int _candidateTile + = DAT_TileMapState::instance.directionTranslationMatrix[sVar1][_direction] + uVar4; + if (DAT_TileMapState::instance.WalkLayer[_candidateTile] != this->searchGeneration + && (DAT_TileMapState::instance.LogicLayer[_candidateTile] & 0x30) == 0) { + DAT_TileMapState::instance.CertainPathLayer[_candidateTile] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[_candidateTile] = (short)this->searchGeneration; + sVar3 = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction] + .short_.xOffset; + DAT_TileMapState::instance.LogicLayer[_candidateTile] + = DAT_TileMapState::instance.LogicLayer[_candidateTile] | 0x10; + this->searchQueue.xQueue[this->searchQueue.writeIndex] = sVar3 + sVar2; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction] + .short_.yOffset + + sVar1; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = _candidateTile; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + _candidateTile + = DAT_TileMapState::instance.directionTranslationMatrix[sVar1][_direction + 1] + uVar4; + if (DAT_TileMapState::instance.WalkLayer[_candidateTile] != this->searchGeneration + && (DAT_TileMapState::instance.LogicLayer[_candidateTile] & 0x30) == 0) { + DAT_TileMapState::instance.CertainPathLayer[_candidateTile] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[_candidateTile] = (short)this->searchGeneration; + sVar3 = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction + 1] + .short_.xOffset; + DAT_TileMapState::instance.LogicLayer[_candidateTile] + = DAT_TileMapState::instance.LogicLayer[_candidateTile] | 0x10; + this->searchQueue.xQueue[this->searchQueue.writeIndex] = sVar3 + sVar2; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction + 1] + .short_.yOffset + + sVar1; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = _candidateTile; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + _candidateTile + = DAT_TileMapState::instance.directionTranslationMatrix[sVar1][_direction + 2] + uVar4; + if (DAT_TileMapState::instance.WalkLayer[_candidateTile] != this->searchGeneration + && (DAT_TileMapState::instance.LogicLayer[_candidateTile] & 0x30) == 0) { + DAT_TileMapState::instance.CertainPathLayer[_candidateTile] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[_candidateTile] = (short)this->searchGeneration; + sVar3 = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction + 2] + .short_.xOffset; + DAT_TileMapState::instance.LogicLayer[_candidateTile] + = DAT_TileMapState::instance.LogicLayer[_candidateTile] | 0x10; + this->searchQueue.xQueue[this->searchQueue.writeIndex] = sVar3 + sVar2; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction + 2] + .short_.yOffset + + sVar1; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = _candidateTile; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + _candidateTile + = DAT_TileMapState::instance.directionTranslationMatrix[sVar1][_direction + 3] + uVar4; + if (DAT_TileMapState::instance.WalkLayer[_candidateTile] != this->searchGeneration + && (DAT_TileMapState::instance.LogicLayer[_candidateTile] & 0x30) == 0) { + DAT_TileMapState::instance.CertainPathLayer[_candidateTile] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[_candidateTile] = (short)this->searchGeneration; + sVar3 = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction + 3] + .short_.xOffset; + DAT_TileMapState::instance.LogicLayer[_candidateTile] + = DAT_TileMapState::instance.LogicLayer[_candidateTile] | 0x10; + this->searchQueue.xQueue[this->searchQueue.writeIndex] = sVar3 + sVar2; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction + 3] + .short_.yOffset + + sVar1; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = _candidateTile; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + } + + this->searchQueue.readIndex = this->searchQueue.readIndex + 1; + if (0x13a10 <= (int)this->searchQueue.readIndex) { + this->searchQueue.readIndex = 0; + } + } + return; + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/setupBabyTreeLocationInfo.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/setupBabyTreeLocationInfo.cpp new file mode 100644 index 0000000000..04ad4cc42a --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/setupBabyTreeLocationInfo.cpp @@ -0,0 +1,156 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/IO/LowLevelMemory.func.hpp" +#include "OpenSHC/Map/Location/Point8ShortXY.hpp" +#include "OpenSHC/Map/Trees/TreeType.hpp" +#include "OpenSHC/Map/Trees/TreeTypeShort.hpp" + +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_LandscapeState.hpp" +#include "OpenSHC/Globals/DAT_LowLevelMemory.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + + using OpenSHC::Map::Location::Point8ShortXY; + using OpenSHC::Map::Trees::TreeType; + using OpenSHC::Map::Trees::TreeTypeShort; + + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x0049C020 + undefined4 PathFindingState::setupBabyTreeLocationInfo(int param_1, int treeType, uint x, uint y) + { + int (*paiVar8)[8]; + this->ALG_ResultTile = 0; + this->ALG_ResultY = 0; + this->ALG_ResultX = 0; + if (399 < x || 399 < y) { + return (undefined4)(0); + } + if (DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[y * 400 + x] == '\0') { + return (undefined4)(0); + } + this->calculations = this->calculations + 1; + this->searchGeneration = this->searchGeneration + 1; + if (32000 < this->searchGeneration) { + this->searchGeneration = 1; + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 0x27420, '\0', (void*)((int)(DAT_TileMapState::instance.WalkLayer))); + } + this->searchQueue.readIndex = 0; + this->searchQueue.writeIndex = 1; + this->searchQueue.currentDistance = 1; + this->searchQueue.yQueue[0] = (short)y; + this->searchQueue.xQueue[0] = (short)x; + int _startTile = DAT_ViewportRenderState::instance.translationMatrix[y].addXgetTile + x; + this->searchQueue.tilesQueue[0] = _startTile; + DAT_TileMapState::instance.CertainPathLayer[_startTile] = (short)this->searchQueue.currentDistance; + DAT_TileMapState::instance.WalkLayer[this->searchQueue.tilesQueue[0]] = (short)this->searchGeneration; + if (this->searchQueue.readIndex != this->searchQueue.writeIndex) { + while (true) { + int iVar4 = this->searchQueue.tilesQueue[this->searchQueue.readIndex]; + if (iVar4 < 0) { + break; + } + if (0x13a10 <= iVar4) { + break; + } + this->searchQueue.currentDistance = (int)DAT_TileMapState::instance.CertainPathLayer[iVar4]; + if (0x13a10 < (int)this->searchQueue.currentDistance) { + return (undefined4)(0); + } + if ((int)this->searchQueue.currentDistance > param_1) { + return (undefined4)(1); + } + int sVar1 = (int)this->searchQueue.yQueue[this->searchQueue.readIndex]; + int sVar2 = (int)this->searchQueue.xQueue[this->searchQueue.readIndex]; + for (int _direction = 0; _direction < 8; _direction = _direction + 1) { + int iVar5 = DAT_TileMapState::instance.directionTranslationMatrix[sVar1][_direction] + iVar4; + if (DAT_TileMapState::instance.WalkLayer[iVar5] != this->searchGeneration) { + int iVar6 = (int)DAT_TileMapState::instance.OrganismLayer[iVar5]; + if ((iVar6 == 0) || (1999 < iVar6)) { + int _building = DAT_TileMapState::instance.BuildingLayer[iVar5]; + if (_building != 0) { + switch (DAT_BuildingsState::instance.buildings[_building].buildingType) { + case OpenSHC::Map::Buildings::BT_WOODCUTTERSHUT: + case OpenSHC::Map::Buildings::BT_QUARRY: + case OpenSHC::Map::Buildings::BT_WHEATFARM: + case OpenSHC::Map::Buildings::BT_HOPFARM: + case OpenSHC::Map::Buildings::BT_APPLEFARM: + case OpenSHC::Map::Buildings::BT_DAIRYFARM: + case OpenSHC::Map::Buildings::BT_SIGNPOST: + case OpenSHC::Map::Buildings::BT_POND: + break; + default: + goto switchD_0049c1f0_caseD_4; + } + } + if ((DAT_TileMapState::instance.LogicLayer[iVar5] & 0x703e25b5U) == 0) { + if (treeType == 1) { + if ((DAT_TileMapState::instance.Logic2Layer[iVar5] & 0x90) == 0) { + LAB_0049c26a: + DAT_TileMapState::instance.CertainPathLayer[iVar5] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[iVar5] = (short)this->searchGeneration; + this->searchQueue.xQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance + .clockwiseCardinalTranslationMatrix[_direction] + .short_.xOffset + + sVar2; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance + .clockwiseCardinalTranslationMatrix[_direction] + .short_.yOffset + + sVar1; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = iVar5; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + } else if ((DAT_TileMapState::instance.Logic2Layer[iVar5] & 0x90) != 0) + goto LAB_0049c26a; + } + } else { + TreeTypeShort TVar3 = DAT_LandscapeState::instance.trees[iVar6].treeType; + if (TVar3 == (TreeType)1) { + return (undefined4)(0); + } + if (TVar3 == (TreeType)2) { + return (undefined4)(0); + } + if (TVar3 == (TreeType)3) { + return (undefined4)(0); + } + if (TVar3 == (TreeType)4) { + return (undefined4)(0); + } + } + } + } + + this->searchQueue.readIndex = this->searchQueue.readIndex + 1; + if (0x13a10 <= (int)this->searchQueue.readIndex) { + this->searchQueue.readIndex = 0; + } + if (this->searchQueue.readIndex == this->searchQueue.writeIndex) { + return (undefined4)(0); + } + } + } + switchD_0049c1f0_caseD_4: + return (undefined4)(0); + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/someBinaryAlgFunctionPathFinding.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/someBinaryAlgFunctionPathFinding.cpp new file mode 100644 index 0000000000..8d31266250 --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/someBinaryAlgFunctionPathFinding.cpp @@ -0,0 +1,93 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/IO/LowLevelMemory.func.hpp" +#include "OpenSHC/Map/Location/Point8ShortXY.hpp" + +#include "OpenSHC/Globals/DAT_LowLevelMemory.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_UnitsState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + using OpenSHC::Map::Location::Point8ShortXY; + + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x0049D640 + undefined4 PathFindingState::someBinaryAlgFunctionPathFinding(int param_1) + { + int (*paiVar7)[8]; + this->searchGeneration = this->searchGeneration + 1; + if (32000 < this->searchGeneration) { + this->searchGeneration = 1; + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 0x27420, '\0', (void*)((int)(DAT_TileMapState::instance.WalkLayer))); + } + this->searchQueue.readIndex = 0; + this->searchQueue.writeIndex = 1; + this->searchQueue.currentDistance = 1; + ushort uVar1 = DAT_TileMapState::instance.PathConnectionLayer[DAT_UnitsState::instance.units[param_1].tile]; + this->searchQueue.yQueue[0] = DAT_UnitsState::instance.units[param_1].y; + this->searchQueue.xQueue[0] = DAT_UnitsState::instance.units[param_1].x; + int _startTile = DAT_UnitsState::instance.units[param_1].tile; + this->searchQueue.tilesQueue[0] = _startTile; + DAT_TileMapState::instance.CertainPathLayer[_startTile] = (short)this->searchQueue.currentDistance; + DAT_TileMapState::instance.WalkLayer[this->searchQueue.tilesQueue[0]] = (short)this->searchGeneration; + while (this->searchQueue.readIndex != this->searchQueue.writeIndex) { + int iVar4 = this->searchQueue.tilesQueue[this->searchQueue.readIndex]; + if (iVar4 < 0) { + return (undefined4)(1); + } + if (0x13a10 <= iVar4) { + return (undefined4)(1); + } + int sVar2 = (int)this->searchQueue.xQueue[this->searchQueue.readIndex]; + int sVar3 = (int)this->searchQueue.yQueue[this->searchQueue.readIndex]; + this->searchQueue.currentDistance = (int)DAT_TileMapState::instance.CertainPathLayer[iVar4]; + if (0x13a10 < (int)this->searchQueue.currentDistance) { + return (undefined4)(1); + } + for (int _direction = 0; _direction < 8; _direction = _direction + 1) { + int iVar5 = DAT_TileMapState::instance.directionTranslationMatrix[sVar3][_direction] + iVar4; + if ((DAT_TileMapState::instance.WalkLayer[iVar5] != this->searchGeneration) + && (DAT_TileMapState::instance.PathConnectionLayer[iVar5] == uVar1)) { + if ((DAT_TileMapState::instance.LogicLayer[iVar5] & 0x10000100U) == 0 + || (DAT_TileMapState::instance.LogicLayer[iVar5] & 0x400000U) != 0) { + return (undefined4)(0); + } + DAT_TileMapState::instance.CertainPathLayer[iVar5] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[iVar5] = (short)this->searchGeneration; + this->searchQueue.xQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction] + .short_.xOffset + + sVar2; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction] + .short_.yOffset + + sVar3; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = iVar5; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + } + + this->searchQueue.readIndex = this->searchQueue.readIndex + 1; + if (0x13a10 <= (int)this->searchQueue.readIndex) { + this->searchQueue.readIndex = 0; + } + } + return (undefined4)(1); + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/spawnUnitAndAddToTribe.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/spawnUnitAndAddToTribe.cpp new file mode 100644 index 0000000000..129e26a8b8 --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/spawnUnitAndAddToTribe.cpp @@ -0,0 +1,86 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" +#include "OpenSHC/Map/Units/TribesState.func.hpp" +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Map/Navigation/Algorithms/XYPair.hpp" + +#include "OpenSHC/Globals/DAT_GameState.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_TribesState.hpp" +#include "OpenSHC/Globals/DAT_UnitsState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + using OpenSHC::Map::Navigation::Algorithms::XYPair; + + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x004A67D0 + void PathFindingState::spawnUnitAndAddToTribe( + int playerID, int displayColor, int count, UnitType unitType, undefined4 tribeID) + { + int* local_4; + int _tile; + this->calculations = this->calculations + 1; + int iVar2 = -1; + this->searchQueue.readIndex = 0; + if (this->searchQueue.writeIndex != 0) { + local_4 = &DAT_GameState::instance.mapAndTime.somePairArray[0].y; + do { + uint _y = (uint)this->searchQueue.yQueue[this->searchQueue.readIndex]; + _tile = this->searchQueue.tilesQueue[this->searchQueue.readIndex]; + uint _x = _tile - DAT_ViewportRenderState::instance.translationMatrix[_y].addXgetTile; + if (DAT_TileMapState::instance.CertainPathLayer[_tile] != 100) { + int _unitID_2 = MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::spawnUnit, + DAT_UnitsState::ptr)(playerID, displayColor, (int)(_x * 8), (int)(_y * 8), 8, unitType); + if (_unitID_2 != 0) { + count = count + -1; + MACRO_CALL_MEMBER(OpenSHC::Map::Units::TribesState_Func::addUnitToTribe, + DAT_TribesState::ptr)(_unitID_2, tribeID); + } + if (count <= 0) { + return; + } + MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::PathFindingState_Func::budgetFloodFillOnCertainPathLayer, this)( + _x, _y, 10, 2); + ((XYPair*)(local_4 + -1))->x = _x; + *local_4 = _y; + local_4 = local_4 + 2; + iVar2 = _tile; + } + if (0x117cdef < (int)local_4) + break; + this->searchQueue.readIndex = this->searchQueue.readIndex + 1; + if (0x13a10 <= (int)this->searchQueue.readIndex) { + this->searchQueue.readIndex = 0; + } + } while (this->searchQueue.readIndex != this->searchQueue.writeIndex); + } + if ((0 < count) && (iVar2 != -1)) { + int sVar1 = (short)DAT_ViewportRenderState::instance.tileTranslationMatrix_YComponent[iVar2]; + _tile = DAT_ViewportRenderState::instance.translationMatrix[sVar1].addXgetTile; + do { + int _unitID + = MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::spawnUnit, DAT_UnitsState::ptr)( + playerID, displayColor, (iVar2 - _tile) * 8, (int)(sVar1 * 8), 8, unitType); + if (_unitID != 0) { + MACRO_CALL_MEMBER(OpenSHC::Map::Units::TribesState_Func::addUnitToTribe, DAT_TribesState::ptr)( + _unitID, tribeID); + } + count = count + -1; + } while (0 < count); + } + return; + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/spreadAlgorithmForFlagsAndBraziersUnk.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/spreadAlgorithmForFlagsAndBraziersUnk.cpp new file mode 100644 index 0000000000..0b6cd6247d --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/spreadAlgorithmForFlagsAndBraziersUnk.cpp @@ -0,0 +1,165 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/IO/LowLevelMemory.func.hpp" +#include "OpenSHC/Map/Buildings/BuildingsState.func.hpp" +#include "OpenSHC/Map/Entities/EntityState.func.hpp" +#include "OpenSHC/Commands/MappersEnum.hpp" +#include "OpenSHC/Game/GameMode2.hpp" +#include "OpenSHC/Map/Location/Point8ShortXY.hpp" + +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_EntityState.hpp" +#include "OpenSHC/Globals/DAT_GameCore.hpp" +#include "OpenSHC/Globals/DAT_GameState.hpp" +#include "OpenSHC/Globals/DAT_GameSynchronyState.hpp" +#include "OpenSHC/Globals/DAT_LowLevelMemory.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + + using OpenSHC::Commands::MappersEnum; + using OpenSHC::Game::GameMode2; + using OpenSHC::Map::Location::Point8ShortXY; + + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + WARNING: Enum "DPSEND_EnumInt": Some values do not have unique names + */ + /* + WARNING: Enum "DPERRInt": Some values do not have unique names + */ + /* + decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x004A2A90 + undefined4 PathFindingState::spreadAlgorithmForFlagsAndBraziersUnk( + int playerID, uint x, uint y, int param_4, int param_5) + { + int* piVar1; + int sVar2; + int tile; + uint uVar3; + int iVar4; + int iVar5; + int (*paiVar7)[8]; + int local_8; + int local_4; + uVar3 = y; + if (399 < x || 399 < y) { + return (undefined4)(0); + } + if (DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[y * 400 + x] == '\0') { + return (undefined4)(0); + } + this->calculations = this->calculations + 1; + this->searchGeneration = this->searchGeneration + 1; + if (32000 < this->searchGeneration) { + this->searchGeneration = 1; + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 0x27420, '\0', (void*)((int)(DAT_TileMapState::instance.WalkLayer))); + } + this->searchQueue.readIndex = 0; + this->searchQueue.writeIndex = 1; + this->searchQueue.currentDistance = 1; + this->searchQueue.yQueue[0] = (short)uVar3; + this->searchQueue.tilesQueue[0] + = DAT_ViewportRenderState::instance.translationMatrix[uVar3].addXgetTile + x; + this->searchQueue.xQueue[0] = (short)x; + DAT_TileMapState::instance.WalkLayer[this->searchQueue.tilesQueue[0]] = (short)this->searchGeneration; + DAT_TileMapState::instance.CertainPathLayer[this->searchQueue.tilesQueue[0]] = 1; + if (this->searchQueue.readIndex != this->searchQueue.writeIndex) { + while ( + (tile = this->searchQueue.tilesQueue[this->searchQueue.readIndex], -1 < tile && (tile < 0x13a10))) { + local_4 = (int)this->searchQueue.xQueue[this->searchQueue.readIndex]; + sVar2 = (int)this->searchQueue.yQueue[this->searchQueue.readIndex]; + this->searchQueue.currentDistance = (int)DAT_TileMapState::instance.CertainPathLayer[tile]; + if (0x13a10 < (int)this->searchQueue.currentDistance) { + return (undefined4)(0); + } + if ((int)this->searchQueue.currentDistance > param_4) { + return (undefined4)(0); + } + iVar5 = (int)DAT_TileMapState::instance.EntityLayer[tile]; + if (DAT_TileMapState::instance.EntityLayer[tile] != 0) { + for (int _step = 1; _step < 10; _step = _step + 1) { + if (DAT_EntityState::instance.entityArray[iVar5].owner == playerID) { + switch (DAT_EntityState::instance.entityArray[iVar5].entityType) { + case OpenSHC::Map::Entities::ET_BRAZIER: + if ((DAT_GameCore::instance.gameMode_2 == OpenSHC::Game::GM_SIEGE_THAT) + && (DAT_EntityState::instance.entityArray[iVar5].logicalState != 3)) { + if (param_5 == 0) { + return (undefined4)(1); + } + local_8 = 0; + y = 0; + MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::getBuildingCost, + DAT_BuildingsState::ptr)( + OpenSHC::Commands::M_MAPPER_BRAZIER, &local_8, (int*)&y); + piVar1 + = DAT_GameState::instance + .playerDataArray[DAT_GameSynchronyState::instance.currentPlayerSlotID] + .startResources + + 0xf; + *piVar1 = *piVar1 + y; + } + case OpenSHC::Map::Entities::ET_FLAG_1: + case OpenSHC::Map::Entities::ET_FLAG_4: + case OpenSHC::Map::Entities::ET_FLAG_2: + case OpenSHC::Map::Entities::ET_FLAG_3: + case OpenSHC::Map::Entities::ET_HEADS_ON_SPIKES: + if (param_5 == 0) { + return (undefined4)(1); + } + MACRO_CALL_MEMBER(OpenSHC::Map::Entities::EntityState_Func::destroyEntitiesOnTile, + DAT_EntityState::ptr)(tile); + } + } + iVar4 = (int)DAT_EntityState::instance.entityArray[iVar5].nextEntityOnThisTileByID; + if ((iVar5 == iVar4) || (iVar5 = iVar4, iVar4 == 0)) + break; + } + } + for (int _direction = 0; _direction < 8; _direction = _direction + 2) { + iVar5 = DAT_TileMapState::instance.directionTranslationMatrix[sVar2][_direction] + tile; + if (DAT_TileMapState::instance.WalkLayer[iVar5] != this->searchGeneration + && (DAT_TileMapState::instance.LogicLayer[iVar5] & 0x30) == 0) { + DAT_TileMapState::instance.CertainPathLayer[iVar5] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[iVar5] = (short)this->searchGeneration; + this->searchQueue.xQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction] + .short_.xOffset + + local_4; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction] + .short_.yOffset + + sVar2; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = iVar5; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a0f < this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + } + + this->searchQueue.readIndex = this->searchQueue.readIndex + 1; + if (0x13a0f < this->searchQueue.readIndex) { + this->searchQueue.readIndex = 0; + } + if (this->searchQueue.readIndex == this->searchQueue.writeIndex) { + return (undefined4)(0); + } + } + } + return (undefined4)(0); + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/storeDestinationOptionsUnk.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/storeDestinationOptionsUnk.cpp new file mode 100644 index 0000000000..13a96394f7 --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/storeDestinationOptionsUnk.cpp @@ -0,0 +1,52 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" + +#include "OpenSHC/Globals/DAT_GameState.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x004A6520 + void PathFindingState::storeDestinationOptionsUnk(int signpostID) + { + this->calculations = this->calculations + 1; + int iVar2 = 0; + this->searchQueue.readIndex = 0; + if (this->searchQueue.writeIndex != 0) { + do { + uint y = (uint)this->searchQueue.yQueue[this->searchQueue.readIndex]; + int iVar1 = this->searchQueue.tilesQueue[this->searchQueue.readIndex]; + uint x = iVar1 - DAT_ViewportRenderState::instance.translationMatrix[y].addXgetTile; + if (DAT_TileMapState::instance.CertainPathLayer[iVar1] != 100) { + MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::PathFindingState_Func::budgetFloodFillOnCertainPathLayer, this)( + x, y, 100, (int)(30)); + DAT_GameState::instance.mapAndTime.unitMoveDestinationXYPairs[signpostID][iVar2].x = x; + DAT_GameState::instance.mapAndTime.unitMoveDestinationXYPairs[signpostID][iVar2].y = y; + iVar2 = iVar2 + 1; + } + if (iVar2 >= 40) { + return; + } + this->searchQueue.readIndex = this->searchQueue.readIndex + 1; + if (80400 <= (int)this->searchQueue.readIndex) { + this->searchQueue.readIndex = 0; + } + } while (this->searchQueue.readIndex != this->searchQueue.writeIndex); + } + return; + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/traceAndCommitPathPlan.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/traceAndCommitPathPlan.cpp new file mode 100644 index 0000000000..40cf343ce2 --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/traceAndCommitPathPlan.cpp @@ -0,0 +1,162 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/Map/Buildings/BuildingsState.func.hpp" +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" + +#include "OpenSHC/Globals/DAT_BuildingDefinedData.hpp" +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_ClimbLogicDefinedData.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x004A97D0 + void PathFindingState::traceAndCommitPathPlan(uint x, uint y, uint x2, uint y2, int param_5) + { + uint uVar3; + int iVar4; + int _buildingAtTile; + uint uVar5; + if (x <= 399 && y <= 399 && DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[y * 400 + x] != '\0' + && x2 <= 399 && y2 <= 399 + && DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[y2 * 400 + x2] != '\0') { + uint tile = DAT_ViewportRenderState::instance.translationMatrix[y2].addXgetTile + x2; + int iVar2 = DAT_ViewportRenderState::instance.translationMatrix[y].addXgetTile; + int sVar1 = DAT_TileMapState::instance.WalkLayer[tile]; + x2 = 0; + this->field49_0x94 = 0; + y = (int)DAT_TileMapState::instance.CertainPathLayer[tile]; + do { + if (tile == iVar2 + x) + break; + uint _theDirection = 8; + uint _startGate = DAT_TileMapState::instance.LogicLayer[tile] & 0x40000000; + uint _startDoor = DAT_TileMapState::instance.LogicLayer[tile] & 0x100; + for (uint _direction = 0; (int)_direction < 8; _direction = _direction + 1) { + if (param_5 == 1) { + if ((DAT_ClimbLogicDefinedData::instance.BitFlagHelperForPathLinkage[_direction] + & DAT_TileMapState::instance.PathLinkageLayer[tile]) + == 0) + continue; + LAB_004a99b6: + uint uVar3 = DAT_TileMapState::instance.directionTranslationMatrix[y2][_direction] + tile; + if (DAT_TileMapState::instance.WalkLayer[uVar3] == sVar1 + && (uVar5 = (uint)DAT_TileMapState::instance.CertainPathLayer[uVar3], + (int)(y - 2) <= (int)uVar5) + && (int)uVar5 < (int)y) { + _theDirection = _direction; + y = uVar5; + x2 = uVar3; + } + } else { + if (param_5 != 2) { + if (param_5 == 3 + && (DAT_ClimbLogicDefinedData::instance.BitFlagHelperForPathLinkage[_direction] + & DAT_TileMapState::instance.PathLinkageLayer[tile]) + == 0) { + if ((_direction & 1) == 0 + && (iVar4 + = DAT_TileMapState::instance.directionTranslationMatrix[y2][_direction] + + tile, + _buildingAtTile = (short)DAT_TileMapState::instance.BuildingLayer[tile], + _buildingAtTile == 0 + && ((short)DAT_TileMapState::instance.BuildingLayer[iVar4] + == _buildingAtTile))) { + if (_startDoor == 0) { + uVar3 = DAT_TileMapState::instance.LogicLayer[iVar4] & 0x100; + goto joined_r0x004a99a9; + } + if ((DAT_TileMapState::instance.LogicLayer[iVar4] & 0x100U) == 0) + goto LAB_004a99b6; + } + continue; + } + goto LAB_004a99b6; + } + if ((DAT_ClimbLogicDefinedData::instance.BitFlagHelperForPathLinkage[_direction] + & DAT_TileMapState::instance.PathLinkageLayer[tile]) + != 0) + goto LAB_004a99b6; + iVar4 = DAT_TileMapState::instance.directionTranslationMatrix[y2][_direction] + tile; + if (_startGate == 0) { + uVar3 = DAT_TileMapState::instance.LogicLayer[iVar4] & 0x40000000; + joined_r0x004a99a9: + if (uVar3 != 0) + goto LAB_004a99b6; + } else if ((DAT_TileMapState::instance.LogicLayer[iVar4] & 0xa5014b1U) == 0) { + if ((uint)DAT_TileMapState::instance.HeightLayer[tile] + <= DAT_TileMapState::instance.HeightLayer[iVar4] + 0x10 + && (int)(DAT_TileMapState::instance.HeightLayer[iVar4] - 0x10) + <= (int)(uint)DAT_TileMapState::instance.HeightLayer[tile]) + goto LAB_004a99b6; + } + } + } + if (_theDirection == 8) { + /* + I guess this increment means "total recomputes of the path linkage layer" + */ + this->DAT_lWys = this->DAT_lWys + 1; + this->searchQueue.pathPlanIndex = 0; + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func:: + updatePathLinkageLayerForEachBuildingAtEachTile, + this)(); + MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::PathFindingState_Func::updateSeparateAreaTileMap, this)(1); + MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::updatePathLinkageLayerForAllBuildings, + DAT_BuildingsState::ptr)(); + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func:: + updatePathLinkageLayerAtTileForSomeLogicalReason, + this)(tile, (int)(y2)); + return; + } + y2 = y2 + + DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_theDirection] + .int_.yOffset; + int _building = DAT_TileMapState::instance.BuildingLayer[x2]; + if ((DAT_TileMapState::instance.LogicLayer[x2] & 0x10000100U) != 0 + && (DAT_TileMapState::instance.LogicLayer[x2] & 2U) == 0 + && (_building == 0 + || (DAT_BuildingDefinedData::instance.BuildingIsGateHouseArray + [(short)DAT_BuildingsState::instance.buildings[_building].buildingType] + == 0))) { + this->field49_0x94 = this->field49_0x94 + 1; + } + _theDirection = _theDirection + 4; + if (7 < (int)_theDirection) { + _theDirection = _theDirection - 8; + } + /* + commit path plan + */ + if ((this->searchQueue.pathPlanIndex & 1) == 0) { + this->searchQueue.ptrPathPlan[(int)this->searchQueue.pathPlanIndex / 2] = (byte)_theDirection; + } else { + this->searchQueue.ptrPathPlan[(int)this->searchQueue.pathPlanIndex / 2] + = this->searchQueue.ptrPathPlan[(int)this->searchQueue.pathPlanIndex / 2] & 0xf; + this->searchQueue.ptrPathPlan[(int)this->searchQueue.pathPlanIndex / 2] + = this->searchQueue.ptrPathPlan[(int)this->searchQueue.pathPlanIndex / 2] + + (byte)_theDirection * '\x10'; + } + tile = x2; + this->searchQueue.pathPlanIndex = this->searchQueue.pathPlanIndex + 1; + } while ((int)this->searchQueue.pathPlanIndex < 800); + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::reverseCurrentPathPlan, this)(); + } + return; + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/tracePathPlanToDestinationViaUnoccupiedTiles.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/tracePathPlanToDestinationViaUnoccupiedTiles.cpp new file mode 100644 index 0000000000..7a92c4bc37 --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/tracePathPlanToDestinationViaUnoccupiedTiles.cpp @@ -0,0 +1,152 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/IO/LowLevelMemory.func.hpp" +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +#include "OpenSHC/Globals/DAT_EntityState.hpp" +#include "OpenSHC/Globals/DAT_LowLevelMemory.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + @return bool whether destination was reached decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ +#pragma optimize("y", off) // original keeps an ebp frame + // FUNCTION: STRONGHOLDCRUSADER 0x0049A370 + BOOLEnum PathFindingState::tracePathPlanToDestinationViaUnoccupiedTiles(uint x, uint y, uint destX, uint destY) + { + byte* _pPathPlan; + int _budget; + int _direction; + int _result; + uint _ppIndex; + Point8* _cardinal; + int* _dirMatrix; + uchar* _linkage; + uchar* _occupancy; + int _fireCount; + int _destTile; + uint _gen; + int _tile; + short* _walkLayer; + if (399 < x || 399 < y) { + return FALSE; + } + if (DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[y * 400 + x] == '\0') { + return FALSE; + } + if (399 < destX || 399 < destY) { + return FALSE; + } + if (DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[destY * 400 + destX] == '\0') { + return FALSE; + } + this->searchGeneration = this->searchGeneration + 1; + if (32000 < this->searchGeneration) { + this->searchGeneration = 1; + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 0x27420, '\0', (void*)((int)(DAT_TileMapState::instance.WalkLayer))); + } + _budget = 0; + _result = 0; + _direction = 0; + _gen = (ushort)this->searchGeneration; + _fireCount = DAT_EntityState::instance.fireCount; + _destTile = DAT_ViewportRenderState::instance.translationMatrix[destY].addXgetTile + destX; + _tile = DAT_ViewportRenderState::instance.translationMatrix[y].addXgetTile + x; + _occupancy = DAT_TileMapState::instance.OccupancyLayer; + _walkLayer = DAT_TileMapState::instance.WalkLayer; + _linkage = DAT_TileMapState::instance.PathLinkageLayer; + _dirMatrix = &DAT_TileMapState::instance.directionTranslationMatrix[0][0]; + _cardinal = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix; + _pPathPlan = this->searchQueue.ptrPathPlan; + _ppIndex = this->searchQueue.pathPlanIndex; + while (true) { + _budget = _budget + 1; + if (399 < _budget) { + break; + } + _walkLayer[_tile] = (short)_gen; + if (_tile == _destTile) { + _result = 1; + break; + } + if (_fireCount != 0 && _occupancy[_tile] != '\0') { + break; + } + byte _links = _linkage[_tile]; + if ((int)y > (int)destY) { + if ((int)x > (int)destX) { + _direction = 7; + if ((_links & 0x80) == 0) { + break; + } + } else if ((int)x < (int)destX) { + _direction = 1; + if ((_links & 2) == 0) { + break; + } + } else { + _direction = 0; + if ((_links & 1) == 0) { + break; + } + } + } else if ((int)y < (int)destY) { + if ((int)x > (int)destX) { + _direction = 5; + if ((_links & 0x20) == 0) { + break; + } + } else if ((int)x < (int)destX) { + _direction = 3; + if ((_links & 8) == 0) { + break; + } + } else { + _direction = 4; + if ((_links & 0x10) == 0) { + break; + } + } + } else if ((int)x > (int)destX) { + _direction = 6; + if ((_links & 0x40) == 0) { + break; + } + } else if ((int)x < (int)destX) { + _direction = 2; + if ((_links & 4) == 0) { + break; + } + } else { + break; + } + _tile = _tile + _dirMatrix[y * 8 + _direction]; + x = x + _cardinal[_direction].int_.xOffset; + y = y + _cardinal[_direction].int_.yOffset; + uint _slot = _ppIndex; + _ppIndex = _ppIndex + 1; + if ((_slot & 1) == 0) { + _pPathPlan[_slot >> 1] = (byte)_direction; + } else { + _pPathPlan[_slot >> 1] = (_pPathPlan[_slot >> 1] & 0xf) | (byte)(_direction << 4); + } + } + this->searchQueue.pathPlanIndex = _ppIndex; + return (BOOLEnum)_result; + } + } +#pragma optimize("", on) +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/tracePathToFriendlyDefensesAndReturnTileUnk.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/tracePathToFriendlyDefensesAndReturnTileUnk.cpp new file mode 100644 index 0000000000..2f69e83887 --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/tracePathToFriendlyDefensesAndReturnTileUnk.cpp @@ -0,0 +1,128 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/IO/LowLevelMemory.func.hpp" + +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_ClimbLogicDefinedData.hpp" +#include "OpenSHC/Globals/DAT_GameState.hpp" +#include "OpenSHC/Globals/DAT_LowLevelMemory.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x004A16C0 + int PathFindingState::tracePathToFriendlyDefensesAndReturnTileUnk(int playerID, uint x, uint y) + { + int (*paiVar7)[8]; + int _candidateTile; + if (399 < x || 399 < y) { + return 0; + } + if (DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[y * 400 + x] == '\0') { + return 0; + } + this->calculations = this->calculations + 1; + this->searchGeneration = this->searchGeneration + 1; + if (32000 < this->searchGeneration) { + this->searchGeneration = 1; + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 160800, '\0', (void*)((int)(DAT_TileMapState::instance.WalkLayer))); + } + this->searchQueue.readIndex = 0; + this->searchQueue.writeIndex = 1; + this->searchQueue.currentDistance = 1; + this->searchQueue.yQueue[0] = (short)y; + this->searchQueue.xQueue[0] = (short)x; + int _startTile = DAT_ViewportRenderState::instance.translationMatrix[y].addXgetTile + x; + this->searchQueue.tilesQueue[0] = _startTile; + DAT_TileMapState::instance.CertainPathLayer[_startTile] = 1; + DAT_TileMapState::instance.WalkLayer[this->searchQueue.tilesQueue[0]] = (short)this->searchGeneration; + while (this->searchQueue.readIndex != this->searchQueue.writeIndex) { + _candidateTile = this->searchQueue.tilesQueue[this->searchQueue.readIndex]; + if (_candidateTile < 0) { + return 0; + } + if (0x13a10 <= _candidateTile) { + return 0; + } + int sVar2 = (int)this->searchQueue.xQueue[this->searchQueue.readIndex]; + int sVar3 = (int)this->searchQueue.yQueue[this->searchQueue.readIndex]; + this->searchQueue.currentDistance = (int)DAT_TileMapState::instance.CertainPathLayer[_candidateTile]; + if (0x13a10 < (int)this->searchQueue.currentDistance) { + return 0; + } + byte bVar1 = DAT_TileMapState::instance.PathLinkageLayer[_candidateTile]; + int iVar6 = 0; + paiVar7 = DAT_TileMapState::instance.directionTranslationMatrix + sVar3; + do { + int iVar5 = (*paiVar7)[0] + _candidateTile; + if (DAT_TileMapState::instance.WalkLayer[iVar5] != this->searchGeneration + && (DAT_TileMapState::instance.LogicLayer[iVar5] & 0x30) == 0) { + if ((DAT_ClimbLogicDefinedData::instance.BitFlagHelperForPathLinkage[iVar6] & bVar1) == 0) { + short sVar4 = DAT_TileMapState::instance.BuildingLayer[iVar5]; + if (sVar4 != 0) { + switch (DAT_BuildingsState::instance.buildings[sVar4].buildingType) { + case OpenSHC::Map::Buildings::BT_MERCENARYPOST: + case OpenSHC::Map::Buildings::BT_BARRACKS: + case OpenSHC::Map::Buildings::BT_MANORHOUSE: + case OpenSHC::Map::Buildings::BT_STONEKEEP: + case OpenSHC::Map::Buildings::BT_STRONGHOLD: + case OpenSHC::Map::Buildings::BT_KEEPFOUR: + case OpenSHC::Map::Buildings::BT_KEEPFIVE: + case OpenSHC::Map::Buildings::BT_GATEHOUSELARGE: + case OpenSHC::Map::Buildings::BT_GATEHOUSESMALL: + case OpenSHC::Map::Buildings::BT_TOWER1: + case OpenSHC::Map::Buildings::BT_TOWER2: + case OpenSHC::Map::Buildings::BT_TOWER3: + case OpenSHC::Map::Buildings::BT_TOWER4: + case OpenSHC::Map::Buildings::BT_TOWER5: + if (DAT_GameState::instance.mapAndTime + .playerTeams[DAT_BuildingsState::instance.buildings[sVar4].owner] + == DAT_GameState::instance.mapAndTime.playerTeams[playerID]) { + return _candidateTile; + } + } + } + } else { + DAT_TileMapState::instance.CertainPathLayer[iVar5] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[iVar5] = (short)this->searchGeneration; + this->searchQueue.xQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[iVar6] + .short_.xOffset + + sVar2; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[iVar6] + .short_.yOffset + + sVar3; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = iVar5; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + } + iVar6 = iVar6 + 1; + paiVar7 = (int (*)[8])(*paiVar7 + 1); + } while (iVar6 < 8); + this->searchQueue.readIndex = this->searchQueue.readIndex + 1; + if (0x13a10 <= (int)this->searchQueue.readIndex) { + this->searchQueue.readIndex = 0; + } + } + return 0; + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/updateAIZoneWithFloodFill0x20.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/updateAIZoneWithFloodFill0x20.cpp new file mode 100644 index 0000000000..9c66da31e4 --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/updateAIZoneWithFloodFill0x20.cpp @@ -0,0 +1,166 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/IO/LowLevelMemory.func.hpp" + +#include "OpenSHC/Globals/DAT_LowLevelMemory.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x0049E9E0 + void PathFindingState::updateAIZoneWithFloodFill0x20(int max, uint x, uint y) + { + if (x > 399 || y > 399) { + return; + } + if (DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[y * 400 + x] == '\0') { + return; + } + this->searchGeneration = this->searchGeneration + 1; + if (32000 < this->searchGeneration) { + this->searchGeneration = 1; + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 0x27420, '\0', (void*)((int)(DAT_TileMapState::instance.WalkLayer))); + } + this->searchQueue.readIndex = 0; + this->searchQueue.writeIndex = 1; + this->searchQueue.currentDistance = 1; + this->searchQueue.yQueue[0] = (short)y; + this->searchQueue.xQueue[0] = (short)x; + this->searchQueue.tilesQueue[0] = DAT_ViewportRenderState::instance.translationMatrix[y].addXgetTile + x; + DAT_TileMapState::instance.WalkLayer[this->searchQueue.tilesQueue[0]] = (short)this->searchGeneration; + DAT_TileMapState::instance.CertainPathLayer[this->searchQueue.tilesQueue[0]] = 1; + if (this->searchQueue.readIndex != this->searchQueue.writeIndex) { + do { + int _tile = this->searchQueue.tilesQueue[this->searchQueue.readIndex]; + DAT_TileMapState::instance.AIInfoLayer[_tile] + = DAT_TileMapState::instance.AIInfoLayer[_tile] | 0x20; + short sVar1 = this->searchQueue.xQueue[this->searchQueue.readIndex]; + short sVar2 = this->searchQueue.yQueue[this->searchQueue.readIndex]; + this->searchQueue.currentDistance = (int)DAT_TileMapState::instance.CertainPathLayer[_tile]; + if ((int)this->searchQueue.currentDistance > max) { + return; + } + for (int iVar3 = 0; iVar3 < 8; iVar3 = iVar3 + 4) { + /* + fixme: why are there nested identical if else statements here? shouldn't it tested the + edge-ness of the candidate !? + */ + if ((DAT_TileMapState::instance.LogicLayer[_tile] & 0x30) == 0) { + int _candidate + = DAT_TileMapState::instance.directionTranslationMatrix[sVar2][iVar3] + _tile; + if (DAT_TileMapState::instance.WalkLayer[_candidate] != this->searchGeneration) { + DAT_TileMapState::instance.CertainPathLayer[_candidate] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[_candidate] = (short)this->searchGeneration; + this->searchQueue.xQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[iVar3] + .short_.xOffset + + sVar1; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[iVar3] + .short_.yOffset + + sVar2; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = _candidate; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + if ((DAT_TileMapState::instance.LogicLayer[_tile] & 0x30) == 0) { + _candidate + = DAT_TileMapState::instance.directionTranslationMatrix[sVar2][iVar3 + 1] + _tile; + if (DAT_TileMapState::instance.WalkLayer[_candidate] != this->searchGeneration) { + DAT_TileMapState::instance.CertainPathLayer[_candidate] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[_candidate] = (short)this->searchGeneration; + this->searchQueue.xQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[iVar3 + 1] + .short_.xOffset + + sVar1; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[iVar3 + 1] + .short_.yOffset + + sVar2; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = _candidate; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + if ((DAT_TileMapState::instance.LogicLayer[_tile] & 0x30) == 0) { + _candidate = DAT_TileMapState::instance.directionTranslationMatrix[sVar2][iVar3 + 2] + + _tile; + if (DAT_TileMapState::instance.WalkLayer[_candidate] != this->searchGeneration) { + DAT_TileMapState::instance.CertainPathLayer[_candidate] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[_candidate] + = (short)this->searchGeneration; + this->searchQueue.xQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance + .clockwiseCardinalTranslationMatrix[iVar3 + 2] + .short_.xOffset + + sVar1; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance + .clockwiseCardinalTranslationMatrix[iVar3 + 2] + .short_.yOffset + + sVar2; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = _candidate; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + if ((DAT_TileMapState::instance.LogicLayer[_tile] & 0x30) == 0 + && (_candidate + = DAT_TileMapState::instance.directionTranslationMatrix[sVar2][iVar3 + 3] + + _tile, + DAT_TileMapState::instance.WalkLayer[_candidate] + != this->searchGeneration)) { + DAT_TileMapState::instance.CertainPathLayer[_candidate] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[_candidate] + = (short)this->searchGeneration; + this->searchQueue.xQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance + .clockwiseCardinalTranslationMatrix[iVar3 + 3] + .short_.xOffset + + sVar1; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance + .clockwiseCardinalTranslationMatrix[iVar3 + 3] + .short_.yOffset + + sVar2; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = _candidate; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + } + } + } + } + this->searchQueue.readIndex = this->searchQueue.readIndex + 1; + if (0x13a10 <= (int)this->searchQueue.readIndex) { + this->searchQueue.readIndex = 0; + } + } while (this->searchQueue.readIndex != this->searchQueue.writeIndex); + } + return; + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/updateClimbData.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/updateClimbData.cpp new file mode 100644 index 0000000000..f253034a38 --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/updateClimbData.cpp @@ -0,0 +1,50 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" + +#include "OpenSHC/Globals/DAT_ClimbLogicDefinedData.hpp" +#include "OpenSHC/Globals/DAT_CurrentClimbDataID.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + + /* + decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x004A9680 + void PathFindingState::updateClimbData() + { + this->numberOfClimbTeleports = 0; + this->debugGreatestClimbLoading = 0; + this->maxClimbDataCount = 0; + DAT_CurrentClimbDataID::instance = 1; + do { + if (this->climbData[DAT_CurrentClimbDataID::instance].canBeUsed != 0) { + this->maxClimbDataCount = DAT_CurrentClimbDataID::instance + 1; + (*DAT_ClimbLogicDefinedData::instance + .updateFunctions[this->climbData[DAT_CurrentClimbDataID::instance].type])(); + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::recountUnitsUsingClimbData, + this)(DAT_CurrentClimbDataID::instance); + if (this->climbData[DAT_CurrentClimbDataID::instance].canBeUsed == 0) { + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::clearClimbData, this)( + DAT_CurrentClimbDataID::instance); + goto LAB_004a9740; + } + this->numberOfClimbTeleports = this->numberOfClimbTeleports + 1; + int iVar1 = this->climbData[DAT_CurrentClimbDataID::instance].numberOfUnitsUsing; + if (iVar1 <= this->debugGreatestClimbLoading) + goto LAB_004a9740; + this->debugGreatestClimbLoading = iVar1; + } + LAB_004a9740: + DAT_CurrentClimbDataID::instance = DAT_CurrentClimbDataID::instance + 1; + if (200 <= (int)DAT_CurrentClimbDataID::instance) { + return; + } + } while (true); + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/updatePathLinkageLayerAtTileForSomeLogicalReason.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/updatePathLinkageLayerAtTileForSomeLogicalReason.cpp new file mode 100644 index 0000000000..4045c9563f --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/updatePathLinkageLayerAtTileForSomeLogicalReason.cpp @@ -0,0 +1,98 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/Globals/DAT_ClimbLogicDefinedData.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x00499DC0 + void PathFindingState::updatePathLinkageLayerAtTileForSomeLogicalReason(int tile, int y) + { + int* _ptrY; + int iVar3; + int uVar4; + int uVar5; + int iVar2 = tile; + uVar5 = 4; + int bVar1 = (char)DAT_TileMapState::instance.PathLinkageLayer[tile]; + _ptrY = DAT_TileMapState::instance.directionTranslationMatrix[y] + 1; + tile = 2; + do { + iVar3 = (*(int (*)[8])(_ptrY + -1))[0] + iVar2; + if ((DAT_TileMapState::instance.LogicLayer[iVar3] & 0x30U) == 0 + && (DAT_TileMapState::instance.LogicLayer[iVar3] & 0x4a5014b1U) == 0) { + if ((bVar1 & (char)DAT_ClimbLogicDefinedData::instance.BitFlagHelperForPathLinkage[uVar5 - 4]) == 0) { + uVar4 = uVar5 % 8; + DAT_TileMapState::instance.PathLinkageLayer[iVar3] + = DAT_TileMapState::instance.PathLinkageLayer[iVar3] + & ~DAT_ClimbLogicDefinedData::instance.BitFlagHelperForPathLinkage[uVar4]; + } else { + uVar4 = uVar5 % 8; + DAT_TileMapState::instance.PathLinkageLayer[iVar3] + = DAT_TileMapState::instance.PathLinkageLayer[iVar3] + | DAT_ClimbLogicDefinedData::instance.BitFlagHelperForPathLinkage[uVar4]; + } + } + iVar3 = *_ptrY + iVar2; + if ((DAT_TileMapState::instance.LogicLayer[iVar3] & 0x30U) == 0 + && (DAT_TileMapState::instance.LogicLayer[iVar3] & 0x4a5014b1U) == 0) { + if ((bVar1 & (char)DAT_ClimbLogicDefinedData::instance.BitFlagHelperForPathLinkage[uVar5 - 3]) == 0) { + uVar4 = (uVar5 + 1) % 8; + DAT_TileMapState::instance.PathLinkageLayer[iVar3] + = DAT_TileMapState::instance.PathLinkageLayer[iVar3] + & ~DAT_ClimbLogicDefinedData::instance.BitFlagHelperForPathLinkage[uVar4]; + } else { + uVar4 = (uVar5 + 1) % 8; + DAT_TileMapState::instance.PathLinkageLayer[iVar3] + = DAT_TileMapState::instance.PathLinkageLayer[iVar3] + | DAT_ClimbLogicDefinedData::instance.BitFlagHelperForPathLinkage[uVar4]; + } + } + iVar3 = _ptrY[1] + iVar2; + if ((DAT_TileMapState::instance.LogicLayer[iVar3] & 0x30U) == 0 + && (DAT_TileMapState::instance.LogicLayer[iVar3] & 0x4a5014b1U) == 0) { + if ((bVar1 & (char)DAT_ClimbLogicDefinedData::instance.BitFlagHelperForPathLinkage[uVar5 - 2]) == 0) { + uVar4 = (uVar5 + 2) % 8; + DAT_TileMapState::instance.PathLinkageLayer[iVar3] + = DAT_TileMapState::instance.PathLinkageLayer[iVar3] + & ~DAT_ClimbLogicDefinedData::instance.BitFlagHelperForPathLinkage[uVar4]; + } else { + uVar4 = (uVar5 + 2) % 8; + DAT_TileMapState::instance.PathLinkageLayer[iVar3] + = DAT_TileMapState::instance.PathLinkageLayer[iVar3] + | DAT_ClimbLogicDefinedData::instance.BitFlagHelperForPathLinkage[uVar4]; + } + } + iVar3 = _ptrY[2] + iVar2; + if ((DAT_TileMapState::instance.LogicLayer[iVar3] & 0x30U) == 0 + && (DAT_TileMapState::instance.LogicLayer[iVar3] & 0x4a5014b1U) == 0) { + if ((bVar1 & (char)DAT_ClimbLogicDefinedData::instance.BitFlagHelperForPathLinkage[uVar5 - 1]) == 0) { + uVar4 = (uVar5 + 3) % 8; + DAT_TileMapState::instance.PathLinkageLayer[iVar3] + = DAT_TileMapState::instance.PathLinkageLayer[iVar3] + & ~DAT_ClimbLogicDefinedData::instance.BitFlagHelperForPathLinkage[uVar4]; + } else { + uVar4 = (uVar5 + 3) % 8; + DAT_TileMapState::instance.PathLinkageLayer[iVar3] + = DAT_TileMapState::instance.PathLinkageLayer[iVar3] + | DAT_ClimbLogicDefinedData::instance.BitFlagHelperForPathLinkage[uVar4]; + } + } + _ptrY = _ptrY + 4; + tile = tile + -1; + uVar5 = uVar5 + 4; + } while (tile != 0); + return; + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/updatePathLinkageLayerBasedOnBuildingsUnk.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/updatePathLinkageLayerBasedOnBuildingsUnk.cpp new file mode 100644 index 0000000000..ad7119eb75 --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/updatePathLinkageLayerBasedOnBuildingsUnk.cpp @@ -0,0 +1,223 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/Map/Buildings/BuildingsState.func.hpp" +#include "OpenSHC/Map/Buildings/BuildingTypeShort.hpp" +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +#include "OpenSHC/Globals/DAT_BuildingDefinedData.hpp" +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_ClimbLogicDefinedData.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + + using OpenSHC::Map::Buildings::BuildingTypeShort; + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x004999C0 + BOOLEnum PathFindingState::updatePathLinkageLayerBasedOnBuildingsUnk(int yUnk, int tile) + { + int iVar6; + int (*paiVar8)[8]; + uint _height; + int _directionIndex; + int _building; + bool bVar9; + bool _skip; + byte _linkageResult; + BOOLEnum _result; + int local_28; + uint local_24; + uint local_20[8]; + BuildingTypeShort _buildingType; + uint _logic; + _logic = DAT_TileMapState::instance.LogicLayer[tile]; + _height = (uint)DAT_TileMapState::instance.HeightLayer[tile]; + _building = (int)DAT_TileMapState::instance.BuildingLayer[tile]; + _result = FALSE; + if ((_logic & 0x10000000) != 0) { + iVar6 = MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::getBuildingHeightForBuildingID, + DAT_BuildingsState::ptr)(_building); + _height = _height + iVar6; + } + local_24 = _height + 0x10; + local_28 = _height - 0x10; + if (_building != 0) { + _buildingType = DAT_BuildingsState::instance.buildings[_building].buildingType; + _result + = (BOOLEnum)(DAT_BuildingDefinedData::instance.BuildingIsGateHouseArray[(short)_buildingType] != 0); + if (DAT_BuildingDefinedData::instance.BuildingIsKeepArray[(short)_buildingType] != 0) { + _result = TRUE; + } + } + int bVar2 = 0; + int bVar4 = 0; + int bVar3 = 0; + int bVar5 = 0; + byte bVar7 = 0; + iVar6 = 0; + _linkageResult = 0; + DAT_TileMapState::instance.PathLinkageLayer[tile] = '\0'; + if ((_logic & 0x800000) == 0) { + if ((_logic & 0x10000000) == 0) { + if ((_logic & 2) == 0 && (_logic & 0x200000) == 0) { + if ((_logic & 0x800) != 0) { + bVar4 = 1; + goto LAB_00499ada; + } + if ((_logic & 0x400000) != 0) { + return _result; + } + if ((_logic & 0x100) != 0) { + bVar3 = 1; + if (DAT_TileMapState::instance.BuildingLayer[tile] != 0) { + iVar6 = 2; + } + goto LAB_00499ada; + } + if ((_logic & 0x4a5014b1) != 0) { + return _result; + } + } + bVar5 = 1; + } else { + bVar2 = 1; + iVar6 = 1; + } + } + LAB_00499ada: + paiVar8 = DAT_TileMapState::instance.directionTranslationMatrix + yUnk; + for (_directionIndex = 0; _directionIndex < 8; + _directionIndex = _directionIndex + 1, paiVar8 = (int (*)[8])(*paiVar8 + 1)) { + int _tile = (*paiVar8)[0] + tile; + _logic = DAT_TileMapState::instance.LogicLayer[_tile]; + local_20[_directionIndex] = _logic; + if ((_logic & 0x200000) == 0) { + if ((_logic & 0x800) != 0) { + if ((iVar6 == 1) || ('\x14' < (char)DAT_TileMapState::instance.DamageLayer[_tile])) + continue; + goto LAB_00499bce; + } + if ((_logic & 2) == 0) { + if ((_logic & 0x400) == 0) { + if ((_logic & 0x10000000) != 0) { + bVar7 = bVar7 + + DAT_ClimbLogicDefinedData::instance.BitFlagHelperForPathLinkage[_directionIndex]; + goto LAB_00499bce; + } + if ((_logic & 0x400000) == 0) { + if ((_logic & 0x100) != 0) { + bVar7 = bVar7 + + DAT_ClimbLogicDefinedData::instance + .BitFlagHelperForPathLinkage[_directionIndex]; + goto LAB_00499bce; + } + if ((_logic & 0x30) == 0) { + bVar9 = (_logic & 0x4a5014b1) == 0; + goto LAB_00499bcc; + } + bVar7 = bVar7 + + DAT_ClimbLogicDefinedData::instance.BitFlagHelperForPathLinkage[_directionIndex]; + } else { + bVar7 = bVar7 + + DAT_ClimbLogicDefinedData::instance.BitFlagHelperForPathLinkage[_directionIndex]; + } + } else if (DAT_BuildingDefinedData::instance.field17_0x1774[(short)DAT_BuildingsState::instance + .buildings[DAT_TileMapState::instance.BuildingLayer[_tile]] + .buildingType] + != FALSE) { + bVar7 = bVar7 + + DAT_ClimbLogicDefinedData::instance.BitFlagHelperForPathLinkage[_directionIndex]; + } + } else if (!bVar2) { + if ((_logic & 0x400) != 0) { + bVar9 = DAT_TileMapState::instance.BuildingLayer[_tile] == 0; + LAB_00499bcc: + if (!bVar9) + continue; + } + goto LAB_00499bce; + } + } else { + LAB_00499bce: + if ((_logic & 0x10000000) == 0) { + if ((_logic & 0x100) == 0 || iVar6 == 0) { + if (((bVar3) || (bVar4)) && (_logic & 0x100) != 0 + && DAT_TileMapState::instance.BuildingLayer[_tile] != 0) { + _skip = (char)DAT_TileMapState::instance.DamageLayer[tile] > 0x14; + } else { + _logic = (uint)DAT_TileMapState::instance.HeightLayer[_tile]; + if ((int)_logic < local_28) + continue; + _skip = (int)_logic > (int)local_24; + } + } else { + _skip = (char)DAT_TileMapState::instance.DamageLayer[_tile] > 0x14; + } + LAB_00499c3f: + if (_skip) + continue; + } else if (!bVar2) { + if (!bVar3) + continue; + _skip = (char)DAT_TileMapState::instance.DamageLayer[tile] > 0x14; + goto LAB_00499c3f; + } + _linkageResult = _linkageResult + | DAT_ClimbLogicDefinedData::instance.BitFlagHelperForPathLinkage[_directionIndex]; + } + } + if (bVar5) { + if ((_linkageResult & 1) == 0 && (bVar7 & 1) != 0) { + if ((_linkageResult & 4) == 0 && (bVar7 & 4) != 0) { + _linkageResult = _linkageResult & 0xfd; + } + if ((_linkageResult & 0x40) == 0 && (bVar7 & 0x40) != 0) { + _linkageResult = _linkageResult & 0x7f; + } + } + if ((_linkageResult & 0x10) == 0 && (bVar7 & 0x10) != 0) { + if ((_linkageResult & 4) == 0 && (bVar7 & 4) != 0) { + _linkageResult = _linkageResult & 0xf7; + } + if ((_linkageResult & 0x40) == 0 && (bVar7 & 0x40) != 0) { + _linkageResult = _linkageResult & 0xdf; + } + } + } else { + if ((local_20[0] & 0x10000100) != 0 && (local_20[2] & 0x10000100) != 0 + && (local_20[1] & 0x10000100) == 0 && (local_20[1] & 2) == 0 && (local_20[0] & 0x800) == 0 + && (local_20[2] & 0x800) == 0) { + _linkageResult = _linkageResult & 0xfd; + } + if ((local_20[0] & 0x10000100) != 0 && (local_20[6] & 0x10000100) != 0 + && (local_20[7] & 0x10000100) == 0 && (local_20[7] & 2) == 0 && (local_20[0] & 0x800) == 0 + && (local_20[6] & 0x800) == 0) { + _linkageResult = _linkageResult & 0x7f; + } + if ((local_20[4] & 0x10000100) != 0 && (local_20[2] & 0x10000100) != 0 + && (local_20[3] & 0x10000100) == 0 && (local_20[3] & 2) == 0 && (local_20[4] & 0x800) == 0 + && (local_20[2] & 0x800) == 0) { + _linkageResult = _linkageResult & 0xf7; + } + if ((local_20[4] & 0x10000100) != 0 && (local_20[6] & 0x10000100) != 0 + && (local_20[5] & 0x10000100) == 0 && (local_20[5] & 2) == 0 && (local_20[4] & 0x800) == 0 + && (local_20[6] & 0x800) == 0) { + _linkageResult = _linkageResult & 0xdf; + } + } + DAT_TileMapState::instance.PathLinkageLayer[tile] = _linkageResult; + return _result; + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/updatePathLinkageLayerForEachBuildingAtEachTile.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/updatePathLinkageLayerForEachBuildingAtEachTile.cpp index e5117e7a5a..8ef7c108fb 100644 --- a/src/OpenSHC/Map/Navigation/PathFindingState/updatePathLinkageLayerForEachBuildingAtEachTile.cpp +++ b/src/OpenSHC/Map/Navigation/PathFindingState/updatePathLinkageLayerForEachBuildingAtEachTile.cpp @@ -1,5 +1,7 @@ #include "../PathFindingState.func.hpp" +#include "OpenSHC/Map/MapConstants.hpp" + #include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" namespace OpenSHC { diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/updatePathLinkageTileMapRelatedToGates.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/updatePathLinkageTileMapRelatedToGates.cpp new file mode 100644 index 0000000000..dcb900f46a --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/updatePathLinkageTileMapRelatedToGates.cpp @@ -0,0 +1,117 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x00499FA0 + void PathFindingState::updatePathLinkageTileMapRelatedToGates(int buildingID) + { + int iVar3; + int _anotherTile; + int iVar4; + int _pl2; + int _middleTileUnk = (int)(short)DAT_BuildingsState::instance.buildings[buildingID].x; + uint _widthOrHeight = DAT_BuildingsState::instance.buildings[buildingID].widthOrHeight; + int _half = (int)_widthOrHeight / 2; + if (DAT_BuildingsState::instance.buildings[buildingID].buildingVariation == 80) { + int iVar2 = (int)(short)DAT_BuildingsState::instance.buildings[buildingID].y; + iVar4 = iVar2 + _half; + _pl2 = DAT_BuildingsState::instance.buildings[buildingID].pathLinkageRelated2; + int _blocked = _pl2 == 2; + _anotherTile = _widthOrHeight + _middleTileUnk; + iVar3 = DAT_ViewportRenderState::instance.translationMatrix[iVar4].addXgetTile + _middleTileUnk + -1; + uint _height = (uint)DAT_TileMapState::instance.HeightLayer[iVar3]; + uint _defaultHeight = (uint)DAT_TileMapState::instance.DefaultHeightLayer[iVar3 + 1]; + if ((DAT_TileMapState::instance.LogicLayer[iVar3] & 0x4a5014b1U) != 0 + || (int)_height > (int)(_defaultHeight + 0x10) || (int)_height < (int)(_defaultHeight - 0x10) + || _blocked != 0) { + DAT_TileMapState::instance.PathLinkageLayer[iVar3] + = DAT_TileMapState::instance.PathLinkageLayer[iVar3] & 0xfb; + DAT_TileMapState::instance.PathLinkageLayer[iVar3 + 1] + = DAT_TileMapState::instance.PathLinkageLayer[iVar3 + 1] & 0xbf; + } else { + DAT_TileMapState::instance.PathLinkageLayer[iVar3] + = DAT_TileMapState::instance.PathLinkageLayer[iVar3] | 4; + DAT_TileMapState::instance.PathLinkageLayer[iVar3 + 1] + = DAT_TileMapState::instance.PathLinkageLayer[iVar3 + 1] | 0x40; + } + _blocked = _pl2 == 2; + _middleTileUnk = DAT_ViewportRenderState::instance.translationMatrix[iVar4].addXgetTile + _anotherTile; + _height = (uint)DAT_TileMapState::instance.HeightLayer[_middleTileUnk]; + _defaultHeight = (uint)DAT_TileMapState::instance.DefaultHeightLayer[_middleTileUnk + -1]; + if ((DAT_TileMapState::instance.LogicLayer[_middleTileUnk] & 0x4a5014b1U) != 0 + || (int)_height > (int)(_defaultHeight + 0x10) || (int)_height < (int)(_defaultHeight - 0x10) + || _blocked != 0) { + DAT_TileMapState::instance.PathLinkageLayer[_middleTileUnk] + = DAT_TileMapState::instance.PathLinkageLayer[_middleTileUnk] & 0xbf; + DAT_TileMapState::instance.PathLinkageLayer[_middleTileUnk + -1] + = DAT_TileMapState::instance.PathLinkageLayer[_middleTileUnk + -1] & 0xfb; + return; + } + DAT_TileMapState::instance.PathLinkageLayer[_middleTileUnk] + = DAT_TileMapState::instance.PathLinkageLayer[_middleTileUnk] | 0x40; + DAT_TileMapState::instance.PathLinkageLayer[_middleTileUnk + -1] + = DAT_TileMapState::instance.PathLinkageLayer[_middleTileUnk + -1] | 4; + return; + } + iVar3 = (int)(short)DAT_BuildingsState::instance.buildings[buildingID].y; + int _xMiddleUnk = _middleTileUnk + _half; + _pl2 = DAT_BuildingsState::instance.buildings[buildingID].pathLinkageRelated2; + int _rowBelow = _widthOrHeight + iVar3; + int _blocked = _pl2 == 2; + int _row = iVar3 + -1; + _middleTileUnk = DAT_ViewportRenderState::instance.translationMatrix[_row].addXgetTile; + iVar4 = DAT_ViewportRenderState::instance.translationMatrix[_row + 1].addXgetTile; + uint uVar5 = (uint)DAT_TileMapState::instance.DefaultHeightLayer[_middleTileUnk + _xMiddleUnk]; + uint _otherHeight = (uint)DAT_TileMapState::instance.DefaultHeightLayer[iVar4 + _xMiddleUnk]; + _middleTileUnk = _middleTileUnk + _xMiddleUnk; + _anotherTile = iVar4 + _xMiddleUnk; + if ((DAT_TileMapState::instance.LogicLayer[_middleTileUnk] & 0x4a5014b1U) != 0 + || (int)uVar5 > (int)(_otherHeight + 0x10) + || (int)uVar5 < (int)(DAT_TileMapState::instance.DefaultHeightLayer[_anotherTile] - 0x10) + || _blocked != 0) { + DAT_TileMapState::instance.PathLinkageLayer[_middleTileUnk] + = DAT_TileMapState::instance.PathLinkageLayer[_middleTileUnk] & 0xef; + DAT_TileMapState::instance.PathLinkageLayer[_anotherTile] + = DAT_TileMapState::instance.PathLinkageLayer[_anotherTile] & 0xfe; + } else { + DAT_TileMapState::instance.PathLinkageLayer[_middleTileUnk] + = DAT_TileMapState::instance.PathLinkageLayer[_middleTileUnk] | 0x10; + DAT_TileMapState::instance.PathLinkageLayer[_anotherTile] + = DAT_TileMapState::instance.PathLinkageLayer[_anotherTile] | 1; + } + _blocked = _pl2 == 2; + _middleTileUnk = DAT_ViewportRenderState::instance.translationMatrix[_rowBelow].addXgetTile; + uVar5 = (uint)DAT_TileMapState::instance.DefaultHeightLayer[_middleTileUnk + _xMiddleUnk]; + iVar4 = DAT_ViewportRenderState::instance.translationMatrix[_rowBelow + -1].addXgetTile + _xMiddleUnk; + _middleTileUnk = _middleTileUnk + _xMiddleUnk; + if ((DAT_TileMapState::instance.LogicLayer[_middleTileUnk] & 0x4a5014b1U) != 0 + || (int)uVar5 > (int)(DAT_TileMapState::instance.DefaultHeightLayer[iVar4] + 0x10) + || (int)uVar5 < (int)(DAT_TileMapState::instance.DefaultHeightLayer[iVar4] - 0x10) || _blocked != 0) { + DAT_TileMapState::instance.PathLinkageLayer[_middleTileUnk] + = DAT_TileMapState::instance.PathLinkageLayer[_middleTileUnk] & 0xfe; + DAT_TileMapState::instance.PathLinkageLayer[iVar4] + = DAT_TileMapState::instance.PathLinkageLayer[iVar4] & 0xef; + return; + } + DAT_TileMapState::instance.PathLinkageLayer[_middleTileUnk] + = DAT_TileMapState::instance.PathLinkageLayer[_middleTileUnk] | 1; + DAT_TileMapState::instance.PathLinkageLayer[iVar4] + = DAT_TileMapState::instance.PathLinkageLayer[iVar4] | 0x10; + return; + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/updatePathLinkageTileMapRelatedToKeeps.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/updatePathLinkageTileMapRelatedToKeeps.cpp new file mode 100644 index 0000000000..203c31756f --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/updatePathLinkageTileMapRelatedToKeeps.cpp @@ -0,0 +1,64 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x0049A1C0 + void PathFindingState::updatePathLinkageTileMapRelatedToKeeps(int buildingID) + { + int iVar3; + int iVar4; + short _orientation = DAT_BuildingsState::instance.buildings[buildingID].orientation; + if (_orientation == 4) { + iVar4 = (int)(short)DAT_BuildingsState::instance.buildings[buildingID].y + -1; + iVar3 = (int)DAT_BuildingsState::instance.buildings[buildingID].widthOrHeight / 2 + + (int)(short)DAT_BuildingsState::instance.buildings[buildingID].x; + int _tile = DAT_ViewportRenderState::instance.translationMatrix[iVar4].addXgetTile + iVar3; + DAT_TileMapState::instance.PathLinkageLayer[_tile] + = DAT_TileMapState::instance.PathLinkageLayer[_tile] | 0x10; + int _tileBelow = DAT_ViewportRenderState::instance.translationMatrix[iVar4 + 1].addXgetTile + iVar3; + DAT_TileMapState::instance.PathLinkageLayer[_tileBelow] + = DAT_TileMapState::instance.PathLinkageLayer[_tileBelow] | 1; + return; + } + if (_orientation == 6) { + iVar3 = (short)DAT_BuildingsState::instance.buildings[buildingID].x + -1; + iVar4 = (int)DAT_BuildingsState::instance.buildings[buildingID].widthOrHeight / 2 + + (int)(short)DAT_BuildingsState::instance.buildings[buildingID].y; + } else { + uint uVar2 = DAT_BuildingsState::instance.buildings[buildingID].widthOrHeight; + if (_orientation != 2) { + iVar4 = (int)(short)DAT_BuildingsState::instance.buildings[buildingID].y + (int)uVar2 + -1; + iVar3 = (int)(short)DAT_BuildingsState::instance.buildings[buildingID].x + (int)uVar2 / 2; + int _tile = DAT_ViewportRenderState::instance.translationMatrix[iVar4].addXgetTile + iVar3; + DAT_TileMapState::instance.PathLinkageLayer[_tile] + = DAT_TileMapState::instance.PathLinkageLayer[_tile] | 0x10; + int _tileBelow = DAT_ViewportRenderState::instance.translationMatrix[iVar4 + 1].addXgetTile + iVar3; + DAT_TileMapState::instance.PathLinkageLayer[_tileBelow] + = DAT_TileMapState::instance.PathLinkageLayer[_tileBelow] | 1; + return; + } + iVar4 = (int)(short)DAT_BuildingsState::instance.buildings[buildingID].y + (int)uVar2 / 2; + iVar3 = (short)DAT_BuildingsState::instance.buildings[buildingID].x + -1 + uVar2; + } + iVar3 = DAT_ViewportRenderState::instance.translationMatrix[iVar4].addXgetTile + iVar3; + DAT_TileMapState::instance.PathLinkageLayer[iVar3] = DAT_TileMapState::instance.PathLinkageLayer[iVar3] | 4; + DAT_TileMapState::instance.PathLinkageLayer[iVar3 + 1] + = DAT_TileMapState::instance.PathLinkageLayer[iVar3 + 1] | 0x40; + return; + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/updatePathLinkageTileMapRelatedToSiegeTower.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/updatePathLinkageTileMapRelatedToSiegeTower.cpp new file mode 100644 index 0000000000..44c65e9895 --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/updatePathLinkageTileMapRelatedToSiegeTower.cpp @@ -0,0 +1,47 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x0049A2E0 + void PathFindingState::updatePathLinkageTileMapRelatedToSiegeTower(int param_1) + { + int iVar4 = (int)(short)DAT_BuildingsState::instance.buildings[param_1].x; + int iVar2 = (int)(short)DAT_BuildingsState::instance.buildings[param_1].y; + int iVar5 = DAT_ViewportRenderState::instance.translationMatrix[iVar2 + -1].addXgetTile + iVar4 + 1; + DAT_TileMapState::instance.PathLinkageLayer[iVar5] + = DAT_TileMapState::instance.PathLinkageLayer[iVar5] | 0x10; + iVar5 = DAT_ViewportRenderState::instance.translationMatrix[iVar2].addXgetTile + iVar4 + 1; + DAT_TileMapState::instance.PathLinkageLayer[iVar5] + = DAT_TileMapState::instance.PathLinkageLayer[iVar5] | 0x11; + iVar5 = DAT_ViewportRenderState::instance.translationMatrix[iVar2 + 2].addXgetTile + iVar4 + 1; + DAT_TileMapState::instance.PathLinkageLayer[iVar5] + = DAT_TileMapState::instance.PathLinkageLayer[iVar5] | 0x11; + iVar5 = DAT_ViewportRenderState::instance.translationMatrix[iVar2 + 3].addXgetTile + iVar4 + 1; + int iVar3 = DAT_ViewportRenderState::instance.translationMatrix[iVar2 + 1].addXgetTile + iVar4; + DAT_TileMapState::instance.PathLinkageLayer[iVar5] = DAT_TileMapState::instance.PathLinkageLayer[iVar5] | 1; + DAT_TileMapState::instance.PathLinkageLayer[iVar3 + -1] + = DAT_TileMapState::instance.PathLinkageLayer[iVar3 + -1] | 4; + DAT_TileMapState::instance.PathLinkageLayer[iVar3] + = DAT_TileMapState::instance.PathLinkageLayer[iVar3] | 0x44; + DAT_TileMapState::instance.PathLinkageLayer[iVar3 + 2] + = DAT_TileMapState::instance.PathLinkageLayer[iVar3 + 2] | 0x44; + DAT_TileMapState::instance.PathLinkageLayer[iVar3 + 3] + = DAT_TileMapState::instance.PathLinkageLayer[iVar3 + 3] | 0x40; + return; + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/updatePathLinkagesInAllEightDirections.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/updatePathLinkagesInAllEightDirections.cpp new file mode 100644 index 0000000000..3fd877cea5 --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/updatePathLinkagesInAllEightDirections.cpp @@ -0,0 +1,51 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x004A5F90 + void PathFindingState::updatePathLinkagesInAllEightDirections(int y, int tile) + { + int (*paiVar1)[8]; + int _someLinkageResult; + _someLinkageResult = 0; + MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::PathFindingState_Func::updatePathLinkageLayerBasedOnBuildingsUnk, this)( + y, tile); + for (int _direction = 0; _direction < 8; _direction = _direction + 1) { + int _nextTile = DAT_TileMapState::instance.directionTranslationMatrix[y][_direction] + tile; + int _nextY + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction].int_.yOffset + y; + BOOLEnum _tileIsKeepUnk = MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::PathFindingState_Func::updatePathLinkageLayerBasedOnBuildingsUnk, this)( + _nextY, _nextTile); + if (_tileIsKeepUnk != FALSE) { + _someLinkageResult = 1; + } + } + + if (_someLinkageResult) { + DAT_BuildingsState::instance.pathLinkageKeepWasUpdatedUnk = 1; + } + return; + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/updateSeparateAreaTileMap.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/updateSeparateAreaTileMap.cpp new file mode 100644 index 0000000000..7e0c644f8c --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/updateSeparateAreaTileMap.cpp @@ -0,0 +1,106 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/IO/LowLevelMemory.func.hpp" +#include "OpenSHC/Map/Buildings/BuildingsState.func.hpp" +#include "OpenSHC/Map/Navigation/PathFindingState/LinkageNeighbourAsm.hpp" +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_GameState.hpp" +#include "OpenSHC/Globals/DAT_LowLevelMemory.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + /* + WARNING: Restarted to delay deadcode elimination for space: ram + */ + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x004995E0 + BOOLEnum PathFindingState::updateSeparateAreaTileMap(int forceUpdate) + { + if (forceUpdate != 0) { + this->toggleUpdateSeparateAreaTileMap = 1; + DAT_GameState::instance.mapAndTime.counterForUpdatingSeparateAreaTileMaps = 0; + } + DAT_GameState::instance.mapAndTime.counterForUpdatingSeparateAreaTileMaps + = DAT_GameState::instance.mapAndTime.counterForUpdatingSeparateAreaTileMaps - 1; + if (0 < DAT_GameState::instance.mapAndTime.counterForUpdatingSeparateAreaTileMaps) { + return FALSE; + } + DAT_GameState::instance.mapAndTime.counterForUpdatingSeparateAreaTileMaps = 200; + if (this->toggleUpdateSeparateAreaTileMap == 0) { + return FALSE; + } + this->field41_0x74 = this->field41_0x74 + 1; + this->toggleUpdateSeparateAreaTileMap = 0; + this->totalZones = 0; + this->sum = 0; + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 0x27420, '\0', (void*)((int)(DAT_TileMapState::instance.PathConnectionLayer))); + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 4000, '\0', (void*)((int)(this->zoneSizesArray))); + MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::updatePathLinkageTileMap, DAT_BuildingsState::ptr)(1); + /* + The eight-neighbour expansion below is handwritten assembly in the original and reaches + the area layer and the queue through these locals; see LinkageNeighbourAsm.hpp. The + queue end lives in the forceUpdate parameter slot, as it does in the original. + */ + ushort* _areaLayer = DAT_TileMapState::instance.PathConnectionLayer; + int* _tilesQueue = this->searchQueue.tilesQueue; + short* _yQueue = this->searchQueue.yQueue; + int* _dirMatrix = &DAT_TileMapState::instance.directionTranslationMatrix[0][0]; + uchar* _linkage = DAT_TileMapState::instance.PathLinkageLayer; + int* _zoneSizes = this->zoneSizesArray; + int _tile; + int _cY; + short _areaID = 1; + int _row = 0; + int* _rowEnd = &DAT_ViewportRenderState::instance.translationMatrix[1].firstTileOfRow; + for (int _first = 0; _first < 80400; _first = _first + 1) { + if (*_rowEnd <= _first) { + _row = _row + 1; + _rowEnd = _rowEnd + 3; + } + if ((char)(short)DAT_TileMapState::instance.PathConnectionLayer[_first] != '\0' + || (DAT_TileMapState::instance.LogicLayer[_first] & 0x4a5014b1) != 0) { + continue; + } + this->searchQueue.tilesQueue[0] = _first; + this->searchQueue.yQueue[0] = _row; + DAT_TileMapState::instance.PathConnectionLayer[_first] = _areaID; + forceUpdate = 1; + int _readIndex = 0; + MACRO_LINKAGE_AREA_LOOP(1, _readIndex, forceUpdate) + _areaID = _areaID + 1; + if (999 < _areaID) { + break; + } + } + this->totalZones = (int)_areaID; + int* _zoneSize = this->zoneSizesArray + 2; + for (int _group = 333; _group != 0; _group = _group - 1) { + this->sum = this->sum + _zoneSize[-1]; + this->sum = this->sum + *_zoneSize; + this->sum = this->sum + _zoneSize[1]; + _zoneSize = _zoneSize + 3; + } + MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::updatePathLinkageTileMap, DAT_BuildingsState::ptr)(0); + return TRUE; + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/updateUnitDeathHeatmapIn3SpacesAroundTile.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/updateUnitDeathHeatmapIn3SpacesAroundTile.cpp new file mode 100644 index 0000000000..c32e9fc1b1 --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/updateUnitDeathHeatmapIn3SpacesAroundTile.cpp @@ -0,0 +1,177 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/IO/LowLevelMemory.func.hpp" + +#include "OpenSHC/Globals/DAT_ClimbLogicDefinedData.hpp" +#include "OpenSHC/Globals/DAT_LowLevelMemory.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x0049E0D0 + void PathFindingState::updateUnitDeathHeatmapIn3SpacesAroundTile(uint x, uint y) + { + int _candidate1; + uint _tile; + if (x > 399 || y > 399) { + return; + } + if (DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[y * 400 + x] == '\0') { + return; + } + this->searchGeneration = this->searchGeneration + 1; + if (32000 < this->searchGeneration) { + this->searchGeneration = 1; + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 0x27420, '\0', (void*)((int)(DAT_TileMapState::instance.WalkLayer))); + } + this->searchQueue.readIndex = 0; + this->searchQueue.writeIndex = 1; + this->searchQueue.currentDistance = 1; + this->searchQueue.yQueue[0] = (short)y; + this->searchQueue.xQueue[0] = (short)x; + this->searchQueue.tilesQueue[0] = DAT_ViewportRenderState::instance.translationMatrix[y].addXgetTile + x; + DAT_TileMapState::instance.CertainPathLayer[this->searchQueue.tilesQueue[0]] = 1; + DAT_TileMapState::instance.WalkLayer[this->searchQueue.tilesQueue[0]] = (short)this->searchGeneration; + if (this->searchQueue.readIndex != this->searchQueue.writeIndex) { + while (_tile = this->searchQueue.tilesQueue[this->searchQueue.readIndex], _tile <= 0x13a0f) { + int _x = (int)this->searchQueue.xQueue[this->searchQueue.readIndex]; + int _y = (int)this->searchQueue.yQueue[this->searchQueue.readIndex]; + int iVar2 = (int)DAT_TileMapState::instance.CertainPathLayer[_tile]; + if (80400 < iVar2) { + this->searchQueue.currentDistance = iVar2; + return; + } + if (3 < iVar2) { + this->searchQueue.currentDistance = iVar2; + return; + } + this->searchQueue.currentDistance = iVar2; + if (DAT_TileMapState::instance.unitDeathHeatMap[_tile] < 250) { + this->searchQueue.currentDistance = (char)DAT_TileMapState::instance.CertainPathLayer[_tile]; + char cVar1 = DAT_TileMapState::instance.unitDeathHeatMap[_tile] + - (char)this->searchQueue.currentDistance; + DAT_TileMapState::instance.unitDeathHeatMap[_tile] = cVar1 + 4; + } + for (int _direction = 0; _direction < 8; _direction = _direction + 4) { + if ((DAT_TileMapState::instance.PathLinkageLayer[_tile] + & DAT_ClimbLogicDefinedData::instance.BitFlagHelperForPathLinkage[_direction]) + != 0 + && (_candidate1 + = DAT_TileMapState::instance.directionTranslationMatrix[_y][_direction] + _tile, + DAT_TileMapState::instance.WalkLayer[_candidate1] != this->searchGeneration)) { + /* + queue tiles walkable in that direction + */ + DAT_TileMapState::instance.CertainPathLayer[_candidate1] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[_candidate1] = (short)this->searchGeneration; + this->searchQueue.xQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction] + .short_.xOffset + + _x; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction] + .short_.yOffset + + _y; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = _candidate1; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + if ((DAT_TileMapState::instance.PathLinkageLayer[_tile] + & DAT_ClimbLogicDefinedData::instance.BitFlagHelperForPathLinkage[_direction + 1]) + != 0 + && (iVar2 + = DAT_TileMapState::instance.directionTranslationMatrix[_y][_direction + 1] + _tile, + DAT_TileMapState::instance.WalkLayer[iVar2] != this->searchGeneration)) { + DAT_TileMapState::instance.CertainPathLayer[iVar2] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[iVar2] = (short)this->searchGeneration; + this->searchQueue.xQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction + 1] + .short_.xOffset + + _x; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction + 1] + .short_.yOffset + + _y; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = iVar2; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + if ((DAT_TileMapState::instance.PathLinkageLayer[_tile] + & DAT_ClimbLogicDefinedData::instance.BitFlagHelperForPathLinkage[_direction + 2]) + != 0 + && (iVar2 + = DAT_TileMapState::instance.directionTranslationMatrix[_y][_direction + 2] + _tile, + DAT_TileMapState::instance.WalkLayer[iVar2] != this->searchGeneration)) { + DAT_TileMapState::instance.CertainPathLayer[iVar2] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[iVar2] = (short)this->searchGeneration; + this->searchQueue.xQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction + 2] + .short_.xOffset + + _x; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction + 2] + .short_.yOffset + + _y; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = iVar2; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + if ((DAT_TileMapState::instance.PathLinkageLayer[_tile] + & DAT_ClimbLogicDefinedData::instance.BitFlagHelperForPathLinkage[_direction + 3]) + != 0 + && (iVar2 + = DAT_TileMapState::instance.directionTranslationMatrix[_y][_direction + 3] + _tile, + DAT_TileMapState::instance.WalkLayer[iVar2] != this->searchGeneration)) { + DAT_TileMapState::instance.CertainPathLayer[iVar2] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[iVar2] = (short)this->searchGeneration; + this->searchQueue.xQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction + 3] + .short_.xOffset + + _x; + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction + 3] + .short_.yOffset + + _y; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = iVar2; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + } + this->searchQueue.readIndex = this->searchQueue.readIndex + 1; + if (0x13a10 <= (int)this->searchQueue.readIndex) { + this->searchQueue.readIndex = 0; + } + if (this->searchQueue.readIndex == this->searchQueue.writeIndex) { + return; + } + } + } + return; + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/updateWalkAndPathLayer.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/updateWalkAndPathLayer.cpp new file mode 100644 index 0000000000..d7419acb3b --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/updateWalkAndPathLayer.cpp @@ -0,0 +1,157 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/IO/LowLevelMemory.func.hpp" +#include "OpenSHC/Map/Location/Point8ShortXY.hpp" + +#include "OpenSHC/Globals/DAT_LowLevelMemory.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + using OpenSHC::Map::Location::Point8ShortXY; + + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x0049AAD0 + void PathFindingState::updateWalkAndPathLayer(int param_1, uint xPosition, uint yPosition) + { + short* psVar6; + int* piVar7; + int iVar8; + if (xPosition > 399 || yPosition > 399) { + return; + } + if (DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[yPosition * 400 + xPosition] == '\0') { + return; + } + this->searchGeneration = this->searchGeneration + 1; + if (32000 < this->searchGeneration) { + this->searchGeneration = 1; + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 160800, '\0', (void*)((int)(DAT_TileMapState::instance.WalkLayer))); + } + this->searchQueue.readIndex = 0; + this->searchQueue.writeIndex = 1; + this->searchQueue.currentDistance = 1; + this->searchQueue.yQueue[0] = (short)yPosition; + this->searchQueue.xQueue[0] = (short)xPosition; + int _startTile = DAT_ViewportRenderState::instance.translationMatrix[yPosition].addXgetTile + xPosition; + this->searchQueue.tilesQueue[0] = _startTile; + DAT_TileMapState::instance.CertainPathLayer[_startTile] = 1; + DAT_TileMapState::instance.WalkLayer[this->searchQueue.tilesQueue[0]] = (short)this->searchGeneration; + while (this->searchQueue.readIndex != this->searchQueue.writeIndex) { + uint uVar3 = this->searchQueue.tilesQueue[this->searchQueue.readIndex]; + if (0x13a0f < uVar3) + break; + int sVar1 = (int)this->searchQueue.yQueue[this->searchQueue.readIndex]; + iVar8 = (int)sVar1; + int sVar2 = (int)this->searchQueue.xQueue[this->searchQueue.readIndex]; + if (iVar8 < this->mappingYRelated) { + this->mappingYRelated = iVar8; + } + if (iVar8 > this->yLimit) { + this->yLimit = iVar8; + } + int iVar4 = (int)sVar2 / 10; + int iVar5 = iVar8 / 10; + DAT_TileMapState::instance.mapping40x40[iVar5][iVar4] = 2; + if (iVar4 < (int)DAT_TileMapState::instance.someYLike) { + DAT_TileMapState::instance.someYLike = iVar4; + } + if (iVar4 > (int)DAT_TileMapState::instance.someYLikeLimit) { + DAT_TileMapState::instance.someYLikeLimit = iVar4; + } + if (iVar5 < (int)DAT_TileMapState::instance.someIndex) { + DAT_TileMapState::instance.someIndex = iVar5; + } + if (iVar5 > (int)DAT_TileMapState::instance.someLimit) { + DAT_TileMapState::instance.someLimit = iVar5; + } + this->searchQueue.currentDistance = (int)DAT_TileMapState::instance.CertainPathLayer[uVar3]; + if ((int)this->searchQueue.currentDistance > param_1) + break; + DAT_TileMapState::instance.ChangedLayer[uVar3] = 2; + piVar7 = DAT_TileMapState::instance.directionTranslationMatrix[iVar8] + 1; + psVar6 = &DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[0].short_.yOffset; + do { + iVar8 = (*(int (*)[8])(piVar7 + -1))[0] + uVar3; + if (DAT_TileMapState::instance.WalkLayer[iVar8] != this->searchGeneration + && (DAT_TileMapState::instance.LogicLayer[iVar8] & 0x30) == 0) { + DAT_TileMapState::instance.CertainPathLayer[iVar8] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[iVar8] = (short)this->searchGeneration; + this->searchQueue.xQueue[this->searchQueue.writeIndex] + = ((Point8ShortXY*)(psVar6 + -2))->xOffset + sVar2; + this->searchQueue.yQueue[this->searchQueue.writeIndex] = *psVar6 + sVar1; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = iVar8; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (80400 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + iVar8 = *piVar7 + uVar3; + if (DAT_TileMapState::instance.WalkLayer[iVar8] != this->searchGeneration + && (DAT_TileMapState::instance.LogicLayer[iVar8] & 0x30) == 0) { + DAT_TileMapState::instance.CertainPathLayer[iVar8] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[iVar8] = (short)this->searchGeneration; + this->searchQueue.xQueue[this->searchQueue.writeIndex] = psVar6[2] + sVar2; + this->searchQueue.yQueue[this->searchQueue.writeIndex] = psVar6[4] + sVar1; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = iVar8; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + iVar8 = piVar7[1] + uVar3; + if (DAT_TileMapState::instance.WalkLayer[iVar8] != this->searchGeneration + && (DAT_TileMapState::instance.LogicLayer[iVar8] & 0x30) == 0) { + DAT_TileMapState::instance.CertainPathLayer[iVar8] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[iVar8] = (short)this->searchGeneration; + this->searchQueue.xQueue[this->searchQueue.writeIndex] = psVar6[6] + sVar2; + this->searchQueue.yQueue[this->searchQueue.writeIndex] = psVar6[8] + sVar1; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = iVar8; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + iVar8 = piVar7[2] + uVar3; + if (DAT_TileMapState::instance.WalkLayer[iVar8] != this->searchGeneration + && (DAT_TileMapState::instance.LogicLayer[iVar8] & 0x30) == 0) { + DAT_TileMapState::instance.CertainPathLayer[iVar8] + = (short)this->searchQueue.currentDistance + 1; + DAT_TileMapState::instance.WalkLayer[iVar8] = (short)this->searchGeneration; + this->searchQueue.xQueue[this->searchQueue.writeIndex] = psVar6[10] + sVar2; + this->searchQueue.yQueue[this->searchQueue.writeIndex] = psVar6[0xc] + sVar1; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = iVar8; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + piVar7 = piVar7 + 4; + psVar6 = psVar6 + 0x10; + } while ((int)psVar6 < (int)&DAT_TerrainDefinedData::instance.field61_0x138); + this->searchQueue.readIndex = this->searchQueue.readIndex + 1; + if (0x13a10 <= (int)this->searchQueue.readIndex) { + this->searchQueue.readIndex = 0; + } + } + DAT_TileMapState::instance.forceUpdateLogicalAndMiscDisplayLayers = 1; + DAT_TileMapState::instance.forceUpdateTextureTilemap = 1; + DAT_TileMapState::instance.forceUpdateGFXLayers = 1; + return; + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/updateWalkLayerAndAIPathCostLayer.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/updateWalkLayerAndAIPathCostLayer.cpp new file mode 100644 index 0000000000..8b3c282dcb --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/updateWalkLayerAndAIPathCostLayer.cpp @@ -0,0 +1,300 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/IO/LowLevelMemory.func.hpp" +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" + +#include "OpenSHC/Globals/DAT_AICState.hpp" +#include "OpenSHC/Globals/DAT_LowLevelMemory.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_PathFindingState.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_TroopValueState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + + /* + WARNING: Enum "MappersEnum": Some values do not have unique names + */ + /* + * Updates the WalkLayer and AI Path Cost Layer using breadth-first search (BFS). * This creates a distance + * map showing how far each tile is from AI zones. * The distance values are stored in the same layer that + * param_5 checks in the siege tent function. * * @param this - PathFindingState object pointer * + * @param param_1 - Maximum distance to calculate (distance limit) * @param param_2 - Target distance for + * candidate collection (0 = don't collect) * @param param_3 - Area/zone ID for navigation check * @param + * playerID - Current player's ID decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x004A7090 + void PathFindingState::updateWalkLayerAndAIPathCostLayer( + int limit, uint borderDistance, dword fromArea, int playerID) + { + int _canNav; + short* psVar3; + int (*paiVar4)[8]; + uint _tile2; + /* + === PATHFINDING STATE INITIALIZATION === Increment active flag value for this search iteration + */ + this->searchGeneration = this->searchGeneration + 1; + /* + Reset flag and clear WalkLayer if exceeding threshold + */ + if (32000 < this->searchGeneration) { + this->searchGeneration = 1; + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 160800, '\0', (void*)((int)(DAT_TileMapState::instance.WalkLayer))); + } + /* + === INITIALIZE BFS QUEUE === + */ + int _tile = 0; + /* + Starting distance + */ + this->searchQueue.currentDistance = 1; + /* + Read position + */ + this->searchQueue.readIndex = 0; + /* + Write position (empty queue) + */ + this->searchQueue.writeIndex = 0; + /* + Track maximum distance found + */ + this->distance = 0; + do { + /* + === SEED QUEUE WITH ALL AI ZONE TILES === Scan entire map (80400 tiles) and add all tiles marked as + AI zones (value 1) This is the "multi-source BFS" starting point Processing in batches of 5 tiles + for optimization Check tile at offset _tile + */ + if (DAT_TileMapState::instance.AIZoneLayer[_tile] == 1) { + /* + Get Y coordinate for this tile + */ + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = (short)DAT_ViewportRenderState::instance.tileTranslationMatrix_YComponent[_tile]; + /* + Add tile to queue + */ + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = _tile; + /* + SET DISTANCE TO 1 FOR ALL AI ZONE TILES This is the SAME data structure that param_5 checks in + the siege tent function! + */ + /* + // Sets to 1 + */ + DAT_TileMapState::instance.SEC_PathfindingCostTileMap1105[*( + int*)((int)DAT_TroopValueState::instance.attackInfo.hackValuesArray + playerID * 0x177bc + + -0x10)][this->searchQueue.tilesQueue[this->searchQueue.writeIndex]] + = (char)this->searchQueue.currentDistance; + /* + Mark as visited + */ + DAT_TileMapState::instance.WalkLayer[this->searchQueue.tilesQueue[this->searchQueue.writeIndex]] + = (short)this->searchGeneration; + /* + Increment queue write position + */ + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (80400 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + /* + Repeat exact same logic for tiles _tile+1, _tile+2, _tile+3, _tile+4 (Unrolled loop for performance + - checking 5 tiles per iteration) + */ + if (DAT_TileMapState::instance.AIZoneLayer[_tile + 1] == 1) { + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = (short)DAT_ViewportRenderState::instance.tileTranslationMatrix_YComponent[_tile + 1]; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = _tile + 1; + DAT_TileMapState::instance.SEC_PathfindingCostTileMap1105[*( + int*)((int)DAT_TroopValueState::instance.attackInfo.hackValuesArray + playerID * 0x177bc + + -0x10)][this->searchQueue.tilesQueue[this->searchQueue.writeIndex]] + = (char)this->searchQueue.currentDistance; + DAT_TileMapState::instance.WalkLayer[this->searchQueue.tilesQueue[this->searchQueue.writeIndex]] + = (short)this->searchGeneration; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (80400 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + if (DAT_TileMapState::instance.AIZoneLayer[_tile + 2] == 1) { + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = (short)DAT_ViewportRenderState::instance.tileTranslationMatrix_YComponent[_tile + 2]; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = _tile + 2; + DAT_TileMapState::instance.SEC_PathfindingCostTileMap1105[*( + int*)((int)DAT_TroopValueState::instance.attackInfo.hackValuesArray + playerID * 0x177bc + + -0x10)][this->searchQueue.tilesQueue[this->searchQueue.writeIndex]] + = (char)this->searchQueue.currentDistance; + DAT_TileMapState::instance.WalkLayer[this->searchQueue.tilesQueue[this->searchQueue.writeIndex]] + = (short)this->searchGeneration; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (80400 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + if (DAT_TileMapState::instance.AIZoneLayer[_tile + 3] == 1) { + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = (short)DAT_ViewportRenderState::instance.tileTranslationMatrix_YComponent[_tile + 3]; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = _tile + 3; + DAT_TileMapState::instance.SEC_PathfindingCostTileMap1105[*( + int*)((int)DAT_TroopValueState::instance.attackInfo.hackValuesArray + playerID * 0x177bc + + -0x10)][this->searchQueue.tilesQueue[this->searchQueue.writeIndex]] + = (char)this->searchQueue.currentDistance; + DAT_TileMapState::instance.WalkLayer[this->searchQueue.tilesQueue[this->searchQueue.writeIndex]] + = (short)this->searchGeneration; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (80400 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + if (DAT_TileMapState::instance.AIZoneLayer[_tile + 4] == 1) { + this->searchQueue.yQueue[this->searchQueue.writeIndex] + = (short)DAT_ViewportRenderState::instance.tileTranslationMatrix_YComponent[_tile + 4]; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = _tile + 4; + DAT_TileMapState::instance.SEC_PathfindingCostTileMap1105[*( + int*)((int)DAT_TroopValueState::instance.attackInfo.hackValuesArray + playerID * 0x177bc + + -0x10)][this->searchQueue.tilesQueue[this->searchQueue.writeIndex]] + = (char)this->searchQueue.currentDistance; + DAT_TileMapState::instance.WalkLayer[this->searchQueue.tilesQueue[this->searchQueue.writeIndex]] + = (short)this->searchGeneration; + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (80400 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + /* + Process all 80400 tiles (entire map) + */ + _tile = _tile + 5; + } while (_tile < 80400); + /* + === MAIN BFS LOOP === Expand outward from all AI zone tiles, calculating distances + */ + while (this->searchQueue.readIndex != this->searchQueue.writeIndex) { + /* + Get current tile from queue + */ + _tile2 = this->searchQueue.tilesQueue[this->searchQueue.readIndex]; + /* + Bounds check + */ + if (0x13a0f < _tile2) { + return; + } + /* + Get Y coordinate of current tile + */ + int sVar1 = (int)this->searchQueue.yQueue[this->searchQueue.readIndex]; + /* + Read the distance value for this tile from the AI path cost layer + */ + this->searchQueue.currentDistance = (uint)DAT_TileMapState::instance.SEC_PathfindingCostTileMap1105[*( + int*)((int)DAT_TroopValueState::instance.attackInfo.hackValuesArray + playerID * 0x177bc + + -0x10)][_tile2]; + /* + Track maximum distance encountered, constitutes extra return value + */ + if ((int)this->searchQueue.currentDistance > this->distance) { + this->distance = this->searchQueue.currentDistance; + } + /* + Stop if we've exceeded the maximum distance limit + */ + if ((int)this->searchQueue.currentDistance > limit) { + return; + } + /* + === COLLECT CANDIDATE TILES AT SPECIFIC DISTANCE === If param_2 is non-zero and tile is at + exactly that distance, and it's reachable from param_3 zone, add to candidate list + */ + if (borderDistance != 0 && this->searchQueue.currentDistance == borderDistance + && (_canNav = MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func:: + calculateCanPlayerUnitsNavigateToAreaFromArea, + DAT_PathFindingState::ptr)(playerID, (dword)((int)(fromArea)), + (dword)((int)((short)DAT_TileMapState::instance.PathConnectionLayer[_tile2])), 0), + _canNav != 0) + && (int)DAT_AICState::instance.aiBorderTilesIndex < 1000) { + /* + Add to candidate array (likely used by AI for strategic placement decisions) + */ + DAT_AICState::instance.aiBorderTiles[DAT_AICState::instance.aiBorderTilesIndex].tile = _tile2; + DAT_AICState::instance.aiBorderTilesIndex = DAT_AICState::instance.aiBorderTilesIndex + 1; + } + /* + === EXPAND TO ADJACENT TILES === Only expand if tile doesn't have blocking terrain 0x100031 + checks for: sea, border, border edge, river + */ + if ((DAT_TileMapState::instance.LogicLayer[_tile2] & 0x100031U) == 0) { + /* + Get pointer to movement direction offsets + */ + paiVar4 = DAT_TileMapState::instance.directionTranslationMatrix + sVar1; + /* + Process all 8 adjacent tiles (cardinal + diagonal directions) + */ + psVar3 = &DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[0].short_.yOffset; + do { + /* + Calculate adjacent tile index + */ + int iVar2 = (*paiVar4)[0] + _tile2; + /* + If adjacent tile hasn't been visited this iteration + */ + if (DAT_TileMapState::instance.WalkLayer[iVar2] != this->searchGeneration) { + /* + SET DISTANCE = CURRENT DISTANCE + 1 This creates the distance map radiating from AI + zones + */ + DAT_TileMapState::instance.SEC_PathfindingCostTileMap1105[*( + int*)((int)DAT_TroopValueState::instance.attackInfo.hackValuesArray + playerID * 0x177bc + + -0x10)][iVar2] = (char)this->searchQueue.currentDistance + '\x01'; + /* + previous line sets pathfinding cost layer Mark as visited + */ + DAT_TileMapState::instance.WalkLayer[iVar2] = (short)this->searchGeneration; + /* + Add adjacent tile to queue + */ + this->searchQueue.yQueue[this->searchQueue.writeIndex] = *psVar3 + sVar1; + this->searchQueue.tilesQueue[this->searchQueue.writeIndex] = iVar2; + /* + Increment queue write position + */ + this->searchQueue.writeIndex = this->searchQueue.writeIndex + 1; + if (0x13a10 <= (int)this->searchQueue.writeIndex) { + this->searchQueue.writeIndex = 0; + } + } + /* + Move to next direction + */ + psVar3 = psVar3 + 8; + paiVar4 = (int (*)[8])(*paiVar4 + 2); + /* + Process all 8 directions + */ + } while ((int)psVar3 < (int)&DAT_TerrainDefinedData::instance.field61_0x138); + } + /* + === ADVANCE TO NEXT TILE IN QUEUE === + */ + this->searchQueue.readIndex = this->searchQueue.readIndex + 1; + if (0x13a10 <= (int)this->searchQueue.readIndex) { + this->searchQueue.readIndex = 0; + } + } + return; + } + + } +} +}