diff --git a/AGENTS.md b/AGENTS.md index 187d9a0ba..c2626a4a9 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -151,8 +151,19 @@ restyling anything large: `__asm` block rather than C++. Functions are never `__declspec(naked)`: write a normal function, keep the compiler-generated statements as C++, and refer to parameters, locals and `this` by name. Prettify offsets with MSVC's struct-member asm syntax (`mov esi, dword ptr [eax]TileMapState.ptr_LogicLayer`) - `::` is not parseable in an - asm operand, so a resolver global cannot be named there. -- a frame pointer plus a `this` spill - the original was built without optimisation. Add `#pragma optimize(, off)` + asm operand, so a resolver global cannot be named there. Where the handwritten block reaches a *global* layer rather + than a `this` field, give it a C++ pointer local and name that local in the asm; the original caches the same bases in + stack slots anyway, so the inner loop still matches. `mov eax, 0` followed by `mov ax, word ptr [..]` is the giveaway + in its own right - that is a hand-rolled `movzx`, which the compiler always emits as one instruction. + Such a block is usually a **macro**: the same instruction stream appears verbatim in several functions and never as a + call, so it belongs in a hand-written `*Asm.hpp` beside them (`NeighbourFlagsAsm.hpp`, `LinkageNeighbourAsm.hpp`). + This has been worth ~45 points per function, three times over. +- a frame pointer plus a `this` spill - the original was built without optimisation, **unless the same function also + reports `mov reg, 0`**. MSVC keeps `ebp` in any function containing an `__asm` block, so for a function with + handwritten assembly the frame pointer says nothing about the optimisation level: reimplement the handwritten part as + inline asm and leave the rest at `/O2`. Checking the prologue settles it - values kept in registers across the entry + tests mean `/O2`. Taking the `/Od` reading instead took `findLinkageBasedPathOrWalkRadius` from 5.1% to 2.8%, where + the same body without the pragma reaches 49.2%. When it really is `/Od`, add `#pragma optimize(, off)` around the function; inline asm alone does not disable optimisation. Then match the reported **frame size** exactly, which is usually the single biggest win, because every local displacement shifts otherwise. Merge locals that share a slot and reproduce dead stores. At `/Od` prefer a nested `if` over an early `continue` (the original inverts the test @@ -234,6 +245,13 @@ of the switch leaving the value it should have set uninitialised. Fixing them wa suspicious dead store is worth decompiling for rather than deleting. Note this is the opposite of the duplicate-tail pattern below, where our shared block should have been two separate branches - check the predecessor count either way. +Duplicating a `LAB_*` is correct C++ but not automatically a better match, so **measure every `goto` removal**. A +`goto` in the decompiler output usually marks a block the original compiler emitted once and jumped to, and writing +the block out twice makes MSVC emit it twice: duplicating the single shared tail in +`setClimbBasedOnClosestClimbData` - two `if` arms that set a coordinate pair and then share the distance test - was +semantically identical and cost **35 points**. Keep the `goto` where the measurement says the original shared the +block, and record that in the commit remark rather than trading match for style. + Diff patterns that were reliable (more in the cheat sheet): - Absolute `DAT_*` addresses in the original asm where the source uses `this->` mean the original accessed the global instance. diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/Constructor_PathFindingState.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/Constructor_PathFindingState.cpp new file mode 100644 index 000000000..b4eac3e66 --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/Constructor_PathFindingState.cpp @@ -0,0 +1,36 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + + /* + decompilerscript: committed: 2025-01-30 21:57:43.216000 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x004A9760 + PathFindingState* PathFindingState::Constructor_PathFindingState() + { + this->field40_0x70 = 0; + this->field41_0x74 = 0; + this->DAT_lWys = 0; + this->notAllAssassinsUnk = 0; + this->DAT_Easy = 0; + this->DAT_Hard = 0; + this->DAT_Test_likely = 0; + this->DAT_Test_gatehouse = 0; + this->searchNonmatchCount = 0; + this->searchMatchCounter = 0; + this->DAT_Ass = 0; + this->calculations = 0; + this->DAT_Mini_spreads = 0; + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::clearPathFindingTileMaps, this)(); + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::clearAllClimbData, this)(); + this->searchGeneration = 1; + return this; + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/LinkageNeighbourAsm.hpp b/src/OpenSHC/Map/Navigation/PathFindingState/LinkageNeighbourAsm.hpp new file mode 100644 index 000000000..9320f9482 --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/LinkageNeighbourAsm.hpp @@ -0,0 +1,243 @@ +/** + HAND WRITTEN - not generated. + + path: 'OpenSHC/Map/Navigation/PathFindingState/LinkageNeighbourAsm.hpp' + + The inner loop of the PathLinkageLayer searches - pushing the eight neighbours of the tile just + taken off the queue - is handwritten assembly in the original, and it is a MACRO: the identical + instruction stream appears verbatim inside findLinkageBasedPathOrWalkRadius (0x00497740), + findSuitableSpawnLocationUnk (0x00497B80) and updateSeparateAreaTileMap (0x004995E0), never as a + call. It is recognisable by + + - "mov eax, 0" followed by "mov ax, word ptr [..]", a zero extension no compiler writes that way + (MSVC emits movzx), + - the search generation and the distance kept in 16-bit registers and compared with "cmp ax, cx" + rather than widened to int, + - every layer base reloaded from its own stack slot before each use instead of being held in a + register across the block. + + Do NOT add "#pragma optimize("", off)" to the enclosing functions. orig_asm.py --stats reports a + frame pointer for all three, but that is caused by the inline assembly itself - MSVC keeps ebp in + any function containing an __asm block - not by a missing /O2. Their prologues are plainly + optimised (the bounds check runs out of registers, "this" stays in esi), and forcing /Od costs + about half of the match. + + PathLinkageLayer bits: 0x01 north, 0x02 north-east, 0x04 east, 0x08 south-east, + 0x10 south, 0x20 south-west, 0x40 west, 0x80 north-west. + + Cardinal neighbours are entered at distance + 1 and diagonal ones at distance + 2; the north and + south rows are reached by adding directionTranslationMatrix[y][0] and [y][4] to the tile. + + The macro expects these locals in the enclosing function, by these names: + + short* _walkLayer, _certainPath the two adjacent short layers + int* _tilesQueue this->searchQueue.tilesQueue + short* _yQueue this->searchQueue.yQueue + int* _dirMatrix directionTranslationMatrix, as a flat int array + 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. + + ID must be unique within the enclosing function; it exists only to keep the assembler labels of two + expansions apart. + + The original reaches the layers through the global instance's absolute address; we load them from + locals because MSVC inline assembly cannot name DAT_TileMapState::instance ("::" is not parseable + in an asm operand). That costs the initial "mov esi, _" instructions and nothing else - the + original reloads from a stack slot at exactly those points anyway. +*/ + +#pragma once + +#include "OpenSHC/Map/TileMapState.hpp" + +// clang-format off + +// One neighbour: OFF is the byte offset on the short layers (-2, 0 or +2), BIT the linkage bit, +// DIST the distance instruction (none for a cardinal step, "add ax, 1" for a diagonal one), +// TILE the tile-delta instruction and YADJ the row-delta instruction. +#define MACRO_LINKAGE_PUSH(ID, N, WRITEIDX, OFF, BIT, DIST, TILE, YADJ) \ + __asm mov ax, word ptr [edi + edx*2 + OFF] \ + __asm cmp ax, word ptr _curGen \ + __asm je push_done_##ID##_##N \ + __asm test bl, BIT \ + __asm je push_done_##ID##_##N \ + __asm mov esi, _certainPath \ + __asm mov ax, word ptr _cCardinalDistance \ + DIST \ + __asm mov cx, word ptr _curGen \ + __asm mov word ptr [esi + edx*2 + OFF], ax \ + __asm mov word ptr [edi + edx*2 + OFF], cx \ + __asm mov ecx, WRITEIDX \ + __asm mov esi, _tilesQueue \ + __asm mov eax, edx \ + TILE \ + __asm mov dword ptr [esi + ecx*4], eax \ + __asm mov eax, _cY \ + YADJ \ + __asm mov esi, _yQueue \ + __asm mov word ptr [esi + ecx*2], ax \ + __asm add WRITEIDX, 1 \ + __asm push_done_##ID##_##N: + +#define MACRO_ASM_SAME +#define MACRO_ASM_INC __asm add eax, 1 +#define MACRO_ASM_DEC __asm sub eax, 1 +#define MACRO_ASM_DIAGONAL __asm add ax, 1 + +// The whole eight-neighbour expansion, in the original's order: west, east, then the north row +// (north, north-west, north-east) and the south row (south, south-west, south-east). +#define MACRO_LINKAGE_EXPAND_NEIGHBOURS(ID, WRITEIDX) \ + __asm mov edx, _tile \ + __asm mov edi, _walkLayer \ + __asm mov ebx, _cLink \ + MACRO_LINKAGE_PUSH(ID, w, WRITEIDX, -2, 0x40, MACRO_ASM_SAME, MACRO_ASM_DEC, MACRO_ASM_SAME) \ + MACRO_LINKAGE_PUSH(ID, e, WRITEIDX, +2, 0x04, MACRO_ASM_SAME, MACRO_ASM_INC, MACRO_ASM_SAME) \ + __asm mov eax, _cY \ + __asm shl eax, 3 \ + __asm mov esi, _dirMatrix \ + __asm add edx, dword ptr [esi + eax*4] \ + MACRO_LINKAGE_PUSH(ID, n, WRITEIDX, 0, 0x01, MACRO_ASM_SAME, MACRO_ASM_SAME, MACRO_ASM_DEC) \ + MACRO_LINKAGE_PUSH(ID, nw, WRITEIDX, -2, 0x80, MACRO_ASM_DIAGONAL, MACRO_ASM_DEC, MACRO_ASM_DEC) \ + MACRO_LINKAGE_PUSH(ID, ne, WRITEIDX, +2, 0x02, MACRO_ASM_DIAGONAL, MACRO_ASM_INC, MACRO_ASM_DEC) \ + __asm mov edx, _tile \ + __asm mov eax, _cY \ + __asm shl eax, 3 \ + __asm add eax, 4 \ + __asm mov esi, _dirMatrix \ + __asm add edx, dword ptr [esi + eax*4] \ + MACRO_LINKAGE_PUSH(ID, s, WRITEIDX, 0, 0x10, MACRO_ASM_SAME, MACRO_ASM_SAME, MACRO_ASM_INC) \ + MACRO_LINKAGE_PUSH(ID, sw, WRITEIDX, -2, 0x20, MACRO_ASM_DIAGONAL, MACRO_ASM_DEC, MACRO_ASM_INC) \ + MACRO_LINKAGE_PUSH(ID, se, WRITEIDX, +2, 0x08, MACRO_ASM_DIAGONAL, MACRO_ASM_INC, MACRO_ASM_INC) + +// The same neighbour, but only entered when OccupancyLayer says the tile is free. TOFF is the +// neighbour's offset in tiles (the occupancy layer holds one byte per tile, so it is not scaled +// like OFF is on the short layers). Needs one more local, "uchar* _occupancy". +#define MACRO_LINKAGE_PUSH_FREE(ID, N, WRITEIDX, OFF, TOFF, BIT, DIST, TILE, YADJ) \ + __asm mov ax, word ptr [edi + edx*2 + OFF] \ + __asm cmp ax, word ptr _curGen \ + __asm je push_done_##ID##_##N \ + __asm test bl, BIT \ + __asm je push_done_##ID##_##N \ + __asm mov esi, _occupancy \ + __asm mov cl, byte ptr [esi + edx + TOFF] \ + __asm cmp cl, 0 \ + __asm jne push_done_##ID##_##N \ + __asm mov esi, _certainPath \ + __asm mov ax, word ptr _cCardinalDistance \ + DIST \ + __asm mov cx, word ptr _curGen \ + __asm mov word ptr [esi + edx*2 + OFF], ax \ + __asm mov word ptr [edi + edx*2 + OFF], cx \ + __asm mov ecx, WRITEIDX \ + __asm mov esi, _tilesQueue \ + __asm mov eax, edx \ + TILE \ + __asm mov dword ptr [esi + ecx*4], eax \ + __asm mov eax, _cY \ + YADJ \ + __asm mov esi, _yQueue \ + __asm mov word ptr [esi + ecx*2], ax \ + __asm add WRITEIDX, 1 \ + __asm push_done_##ID##_##N: + +#define MACRO_LINKAGE_EXPAND_FREE_NEIGHBOURS(ID, WRITEIDX) \ + __asm mov edx, _tile \ + __asm mov edi, _walkLayer \ + __asm mov ebx, _cLink \ + MACRO_LINKAGE_PUSH_FREE(ID, w, WRITEIDX, -2, -1, 0x40, MACRO_ASM_SAME, MACRO_ASM_DEC, MACRO_ASM_SAME) \ + MACRO_LINKAGE_PUSH_FREE(ID, e, WRITEIDX, +2, +1, 0x04, MACRO_ASM_SAME, MACRO_ASM_INC, MACRO_ASM_SAME) \ + __asm mov eax, _cY \ + __asm shl eax, 3 \ + __asm mov esi, _dirMatrix \ + __asm add edx, dword ptr [esi + eax*4] \ + MACRO_LINKAGE_PUSH_FREE(ID, n, WRITEIDX, 0, 0, 0x01, MACRO_ASM_SAME, MACRO_ASM_SAME, MACRO_ASM_DEC) \ + MACRO_LINKAGE_PUSH_FREE(ID, nw, WRITEIDX, -2, -1, 0x80, MACRO_ASM_DIAGONAL, MACRO_ASM_DEC, MACRO_ASM_DEC) \ + MACRO_LINKAGE_PUSH_FREE(ID, ne, WRITEIDX, +2, +1, 0x02, MACRO_ASM_DIAGONAL, MACRO_ASM_INC, MACRO_ASM_DEC) \ + __asm mov edx, _tile \ + __asm mov eax, _cY \ + __asm shl eax, 3 \ + __asm add eax, 4 \ + __asm mov esi, _dirMatrix \ + __asm add edx, dword ptr [esi + eax*4] \ + MACRO_LINKAGE_PUSH_FREE(ID, s, WRITEIDX, 0, 0, 0x10, MACRO_ASM_SAME, MACRO_ASM_SAME, MACRO_ASM_INC) \ + MACRO_LINKAGE_PUSH_FREE(ID, sw, WRITEIDX, -2, -1, 0x20, MACRO_ASM_DIAGONAL, MACRO_ASM_DEC, MACRO_ASM_INC) \ + MACRO_LINKAGE_PUSH_FREE(ID, se, WRITEIDX, +2, +1, 0x08, MACRO_ASM_DIAGONAL, MACRO_ASM_INC, MACRO_ASM_INC) + +// The area flood-fill variant: no distance and no search generation, just "this neighbour has no +// area yet, give it mine". It tests the linkage bit first and walks the north and south rows +// west-to-east, both the other way round from the two search variants above. Needs the locals +// "ushort* _areaLayer" (PathConnectionLayer) and "short _areaID" in place of the layer pair. +#define MACRO_LINKAGE_PUSH_AREA(ID, N, WRITEIDX, OFF, BIT, TILE, YADJ) \ + __asm test bl, BIT \ + __asm je push_done_##ID##_##N \ + __asm mov ax, word ptr [edi + edx*2 + OFF] \ + __asm cmp ax, 0 \ + __asm jne push_done_##ID##_##N \ + __asm mov ax, word ptr _areaID \ + __asm mov word ptr [edi + edx*2 + OFF], ax \ + __asm mov ecx, WRITEIDX \ + __asm mov esi, _tilesQueue \ + __asm mov eax, edx \ + TILE \ + __asm mov dword ptr [esi + ecx*4], eax \ + __asm mov eax, _cY \ + YADJ \ + __asm mov esi, _yQueue \ + __asm mov word ptr [esi + ecx*2], ax \ + __asm add WRITEIDX, 1 \ + __asm push_done_##ID##_##N: + +#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 \ + __asm mov eax, _cY \ + __asm shl eax, 3 \ + __asm mov esi, _dirMatrix \ + __asm add edx, dword ptr [esi + eax*4] \ + MACRO_LINKAGE_PUSH_AREA(ID, nw, WRITEIDX, -2, 0x80, MACRO_ASM_DEC, MACRO_ASM_DEC) \ + MACRO_LINKAGE_PUSH_AREA(ID, n, WRITEIDX, 0, 0x01, MACRO_ASM_SAME, MACRO_ASM_DEC) \ + MACRO_LINKAGE_PUSH_AREA(ID, ne, WRITEIDX, +2, 0x02, MACRO_ASM_INC, MACRO_ASM_DEC) \ + __asm mov edx, _tile \ + __asm mov eax, _cY \ + __asm shl eax, 3 \ + __asm add eax, 4 \ + __asm mov esi, _dirMatrix \ + __asm add edx, dword ptr [esi + eax*4] \ + MACRO_LINKAGE_PUSH_AREA(ID, sw, WRITEIDX, -2, 0x20, MACRO_ASM_DEC, MACRO_ASM_INC) \ + 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 000000000..60d8fa5cc --- /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 000000000..501a876da --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/algFindAttackAngle.cpp @@ -0,0 +1,122 @@ +#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; + int _tileOption; + 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) { + _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 000000000..a31c4f7d4 --- /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/bindPathPlanToAlgorithmStateAndReset.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/bindPathPlanToAlgorithmStateAndReset.cpp index def1d655f..aebd50bd6 100644 --- a/src/OpenSHC/Map/Navigation/PathFindingState/bindPathPlanToAlgorithmStateAndReset.cpp +++ b/src/OpenSHC/Map/Navigation/PathFindingState/bindPathPlanToAlgorithmStateAndReset.cpp @@ -1,4 +1,4 @@ -#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" +#include "../PathFindingState.func.hpp" namespace OpenSHC { namespace Map { diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/budgetFloodFillOnCertainPathLayer.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/budgetFloodFillOnCertainPathLayer.cpp new file mode 100644 index 000000000..a9b3ff293 --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/budgetFloodFillOnCertainPathLayer.cpp @@ -0,0 +1,162 @@ +#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 _candidate; + int _readIndex; + uint _tilesQueue[1000]; + uint _xs[1000]; + uint _ys[1000]; + uint _tile; + uint _xUnk; + uint _yUnk; + _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 { + _tile = _tilesQueue[_readIndex]; + if (0x13a0f < _tile) { + return; + } + if (_writeIndex >= budget) { + return; + } + if (999 <= _writeIndex) { + return; + } + _yUnk = _xs[_readIndex]; + _xUnk = _ys[_readIndex]; + DAT_TileMapState::instance.CertainPathLayer[_tile] = (short)marker; + for (int _direction = 0; _direction < 8; _direction = _direction + 4) { + _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 000000000..9835b3805 --- /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].field239_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 000000000..212204e10 --- /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 000000000..3061fde2d --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/calculatePathKeepAndWallsGatesNotAllowed.cpp @@ -0,0 +1,207 @@ +#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; + int iVar6; + uint _tile; + 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) { + _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) { + 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 000000000..654d375b1 --- /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 000000000..5b8d6f39d --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/certainDamageToUnitsUnk.cpp @@ -0,0 +1,237 @@ +#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 iVar9; + int iVar11; + EntityType local_8; + int local_4; + 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]; + iVar9 = param_1 - DAT_ViewportRenderState::instance.translationMatrix[uVar7].addXgetTile; + 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; + 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 000000000..2dfd5ece4 --- /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/clearActiveClimbDataOfType6And7.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/clearActiveClimbDataOfType6And7.cpp new file mode 100644 index 000000000..08ca1960f --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/clearActiveClimbDataOfType6And7.cpp @@ -0,0 +1,37 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" + +namespace OpenSHC { +namespace Map { + namespace Navigation { + + /* + Iterates all climb data entries (1 to maxClimbDataCount) and calls clearLaddermanWalledData on any entry + that is active (canBeUsed != 0) and has type 6 or 7. The semantics of types 6 and 7 are not yet fully known; + this is likely called during a siege reset or wall state change. renamed by: Claude Sonnet 4.6 + */ + // FUNCTION: STRONGHOLDCRUSADER 0x004A52D0 + void PathFindingState::clearActiveClimbDataOfType6And7() + { + int* piVar2; + int iVar1 = 1; + piVar2 = &this->climbData[1].type; + do { + if (((ClimbData*)(piVar2 + -1))->canBeUsed != 0) { + if (*piVar2 == 6) { + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::clearClimbData, this)(iVar1); + } + if (*piVar2 == 7) { + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::clearClimbData, this)(iVar1); + } + } + iVar1 = iVar1 + 1; + piVar2 = piVar2 + 0x81; + } while (iVar1 < 200); + return; + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/clearAllClimbData.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/clearAllClimbData.cpp index 80fbfda87..0c129f361 100644 --- a/src/OpenSHC/Map/Navigation/PathFindingState/clearAllClimbData.cpp +++ b/src/OpenSHC/Map/Navigation/PathFindingState/clearAllClimbData.cpp @@ -1,4 +1,4 @@ -#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" +#include "../PathFindingState.func.hpp" namespace OpenSHC { namespace Map { diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/clearClimbData.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/clearClimbData.cpp index 693e80c9d..567520e82 100644 --- a/src/OpenSHC/Map/Navigation/PathFindingState/clearClimbData.cpp +++ b/src/OpenSHC/Map/Navigation/PathFindingState/clearClimbData.cpp @@ -1,5 +1,6 @@ +#include "../PathFindingState.func.hpp" + #include "OpenSHC/IO/LowLevelMemory.func.hpp" -#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" #include "OpenSHC/Globals/DAT_LowLevelMemory.hpp" diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/clearPathFindingTileMaps.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/clearPathFindingTileMaps.cpp new file mode 100644 index 000000000..2d6d4522d --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/clearPathFindingTileMaps.cpp @@ -0,0 +1,34 @@ +#include "../PathFindingState.func.hpp" + +#include "OpenSHC/IO/LowLevelMemory.func.hpp" + +#include "OpenSHC/Globals/DAT_LowLevelMemory.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 0x00496E40 + void PathFindingState::clearPathFindingTileMaps() + { + 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)( + 0x13a10, '\0', (void*)((int)(DAT_TileMapState::instance.PathLinkageLayer))); + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 0x27420, '\0', (void*)((int)(DAT_TileMapState::instance.CertainPathLayer))); + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 0x27420, '\0', (void*)((int)(DAT_TileMapState::instance.WalkLayer))); + return; + } + + } +} +} diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/commitUnitPathPlanUsingWalkLayer.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/commitUnitPathPlanUsingWalkLayer.cpp new file mode 100644 index 000000000..2cbc78f56 --- /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 000000000..a68d79419 --- /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 new file mode 100644 index 000000000..19de23dd2 --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/computeAttackVectorsBasedOnXAndY.cpp @@ -0,0 +1,54 @@ +#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 0x004A69F0 + void PathFindingState::computeAttackVectorsBasedOnXAndY(int playerID) + { + this->calculations = this->calculations + 1; + int _index = 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, 100); + DAT_GameState::instance.mapAndTime.attackVectors[playerID][_index].x = x; + DAT_GameState::instance.mapAndTime.attackVectors[playerID][_index].y = y; + DAT_GameState::instance.mapAndTime.attackVectors[playerID][_index].tribeUIDUnk = 0; + DAT_GameState::instance.mapAndTime.attackVectors[playerID][_index].tribeID = 0; + _index = _index + 1; + } + if (_index >= 50) { + 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/computeNextRallyPointDestination.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/computeNextRallyPointDestination.cpp new file mode 100644 index 000000000..bf85e7d0b --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/computeNextRallyPointDestination.cpp @@ -0,0 +1,120 @@ +#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 _cY_2; + 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]; + _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 000000000..cfc6fae0f --- /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 000000000..dada5f6ed --- /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 000000000..c2952105c --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/doMoveFromTileToTile.cpp @@ -0,0 +1,143 @@ +#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) + { + byte bVar2; + uint uVar3; + int _targetTile; + uint uVar4; + ushort _terrainHeight2; + ushort _height; + ushort _terrainHeight; + 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) { + _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))) { + _height = DAT_TileMapState::instance.HeightLayer[tile]; + DAT_UnitsState::instance.units[unitID].animationCycleNumber = 0; + DAT_UnitsState::instance.units[unitID].field306_0x418 = 0; + if (uVar4 == 0) { + _terrainHeight = DAT_TileMapState::instance.HeightLayer[_targetTile]; + 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 { + _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 000000000..3aaed1536 --- /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 000000000..a6417107f --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/findAIZoneWithFlags.cpp @@ -0,0 +1,113 @@ +#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; + int _tile; + 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) { + _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 000000000..1e8814733 --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/findAccessibleWallAndNearbyFreeTile.cpp @@ -0,0 +1,189 @@ +#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; + uint _tile; + 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) { + _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 000000000..9e0972c8f --- /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 000000000..48ce6cd7d --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/findArcherRelatedAttackInfoIndex.cpp @@ -0,0 +1,126 @@ +#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; + 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) { + _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 000000000..1e4c3fef0 --- /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 000000000..592870510 --- /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 000000000..d889ec5b1 --- /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 000000000..050e0c67f --- /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 000000000..e8a5e4369 --- /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 000000000..2fecdbcf5 --- /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 000000000..66881d8af --- /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]].field239_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 000000000..9a447af1e --- /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 000000000..9bb5aa613 --- /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 000000000..6d6261e64 --- /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 000000000..50b1abf95 --- /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 000000000..51ad48c38 --- /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 000000000..57d37e711 --- /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 000000000..a6360f269 --- /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 000000000..cd44b62c2 --- /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 000000000..2b4d8d96c --- /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 000000000..63d122162 --- /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 000000000..60ec15607 --- /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 000000000..52f6a7c46 --- /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 000000000..3a77a62bb --- /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 000000000..399e8770c --- /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 000000000..d523489e4 --- /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 000000000..29004cd03 --- /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 000000000..708396204 --- /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 000000000..96d7d2182 --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/findPathableTileWithoutUnitWithBuildingAtXY.cpp @@ -0,0 +1,136 @@ +#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 iVar2; + 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]; + 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 000000000..0df04d69b --- /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 000000000..3cbe0f953 --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/findSomeSuitableLocationUnk.cpp @@ -0,0 +1,183 @@ +#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; + int iVar8; + 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) { + 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 000000000..5a8740bd8 --- /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 000000000..a32236296 --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/findSupportPointIndex.cpp @@ -0,0 +1,117 @@ +#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 iVar4; + 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) { + 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 000000000..15e0ad721 --- /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 000000000..422a1ab94 --- /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/getComputationalTileIndex.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/getComputationalTileIndex.cpp index b5329ac1f..617aa511e 100644 --- a/src/OpenSHC/Map/Navigation/PathFindingState/getComputationalTileIndex.cpp +++ b/src/OpenSHC/Map/Navigation/PathFindingState/getComputationalTileIndex.cpp @@ -1,4 +1,4 @@ -#include "OpenSHC/Map/Navigation/PathFindingState.hpp" +#include "../PathFindingState.func.hpp" namespace OpenSHC { namespace Map { diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/getGatehouseNearSomethingUnk.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/getGatehouseNearSomethingUnk.cpp new file mode 100644 index 000000000..28a6e5e2c --- /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/getTileInSearchQueue.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/getTileInSearchQueue.cpp index 1b76cae82..fc5f97064 100644 --- a/src/OpenSHC/Map/Navigation/PathFindingState/getTileInSearchQueue.cpp +++ b/src/OpenSHC/Map/Navigation/PathFindingState/getTileInSearchQueue.cpp @@ -1,4 +1,4 @@ -#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" +#include "../PathFindingState.func.hpp" namespace OpenSHC { namespace Map { diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/getTileInSquareBrush.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/getTileInSquareBrush.cpp new file mode 100644 index 000000000..66ecce24e --- /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/getYSmallerThanYLimit.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/getYSmallerThanYLimit.cpp index 7e1e89c5a..98cfd4f13 100644 --- a/src/OpenSHC/Map/Navigation/PathFindingState/getYSmallerThanYLimit.cpp +++ b/src/OpenSHC/Map/Navigation/PathFindingState/getYSmallerThanYLimit.cpp @@ -1,5 +1,4 @@ -#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" -#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" +#include "../PathFindingState.func.hpp" namespace OpenSHC { namespace Map { diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/healUnitsOfPlayerWithinRadius.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/healUnitsOfPlayerWithinRadius.cpp new file mode 100644 index 000000000..d736ed849 --- /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 000000000..a36b0446e --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/igniteFireAtTilesDistanceAway.cpp @@ -0,0 +1,175 @@ +#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; + int _index2; + int _index; + uint _tiles[100]; + uint _tile; + uint _cTile; + this->calculations = this->calculations + 1; + _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; + } + } + _index2 = 0; + if (0 < _index) { + do { + _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 000000000..78dfb7f64 --- /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 000000000..15dba819c --- /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 000000000..04cbd702f --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/isSignPostWithinDistance.cpp @@ -0,0 +1,181 @@ +#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; + int iVar6; + 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) { + 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 000000000..b28c1b626 --- /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 000000000..7e2ff91af --- /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 000000000..a0e58f356 --- /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 000000000..9961636a0 --- /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 000000000..0c3a244a8 --- /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 000000000..0d4a777f4 --- /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 000000000..cba316a5a --- /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; + int _buildingID; + uint _currentTile; + int _currentX; + int _currentY; + uint _logical; + 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) { + _currentTile = this->searchQueue.tilesQueue[this->searchQueue.readIndex]; + if (_currentTile == _tile2) { + return TRUE; + } + if ((this->searchQueue.readIndex >= maxOptionsToTry) || (80400 <= _currentTile)) + break; + _currentX = this->searchQueue.xQueue[this->searchQueue.readIndex]; + _currentY = this->searchQueue.yQueue[this->searchQueue.readIndex]; + this->searchQueue.currentDistance + = (int)DAT_TileMapState::instance.CertainPathLayer[_currentTile]; + if (400 < (int)this->searchQueue.currentDistance) { + return FALSE; + } + _buildingID = DAT_TileMapState::instance.BuildingLayer[_currentTile]; + _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 000000000..fe8b81297 --- /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 000000000..0392348f0 --- /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 000000000..5607e8ec9 --- /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 000000000..173c65250 --- /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 000000000..b26cd1ed0 --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/placeCommemoratingStatueAtGoodLocation.cpp @@ -0,0 +1,198 @@ +#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; + int iVar6; + MappersEnum commandBuildingType; + uint uVar7; + uint uVar8; + int sVar1 = DAT_GameState::instance.playerDataArray[playerID].someKeepRelatedX2; + uVar7 = (uint)sVar1; + int sVar2 = DAT_GameState::instance.playerDataArray[playerID].someKeepRelatedY2; + 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) { + 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 000000000..879e06238 --- /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 000000000..ccce4449f --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/raiseLand2.cpp @@ -0,0 +1,152 @@ +#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) + { + int iVar5; + 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) { + 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 000000000..ad6792f7c --- /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 000000000..d0f49a0cc --- /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 000000000..df7c68351 --- /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/retraceAndCommitPathPlan.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/retraceAndCommitPathPlan.cpp index 592967e90..b264a3e20 100644 --- a/src/OpenSHC/Map/Navigation/PathFindingState/retraceAndCommitPathPlan.cpp +++ b/src/OpenSHC/Map/Navigation/PathFindingState/retraceAndCommitPathPlan.cpp @@ -1,4 +1,4 @@ -#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" +#include "../PathFindingState.func.hpp" namespace OpenSHC { namespace Map { diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/reverseCurrentPathPlan.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/reverseCurrentPathPlan.cpp new file mode 100644 index 000000000..810511cb4 --- /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 000000000..661086ffb --- /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 000000000..f415bb223 --- /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 000000000..45c87ffe9 --- /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 000000000..525749dc9 --- /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 000000000..4f4026ead --- /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; + int _candidateTile; + 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) { + _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 000000000..c7ea160bc --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/setupBabyTreeLocationInfo.cpp @@ -0,0 +1,157 @@ +#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 iVar4; + 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) { + 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 000000000..ce32d56f9 --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/someBinaryAlgFunctionPathFinding.cpp @@ -0,0 +1,95 @@ +#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; + if (this->searchQueue.readIndex != this->searchQueue.writeIndex) { + do { + 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; + } + } while (this->searchQueue.readIndex != this->searchQueue.writeIndex); + } + 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 000000000..972132206 --- /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.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 000000000..0b6cd6247 --- /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 000000000..13a96394f --- /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 000000000..40cf343ce --- /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 000000000..7a92c4bc3 --- /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 000000000..2f69e8388 --- /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 000000000..9c66da31e --- /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 000000000..62b766b3f --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/updateClimbData.cpp @@ -0,0 +1,51 @@ +#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() + { + int iVar1; + 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; + 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 000000000..4045c9563 --- /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 000000000..ad7119eb7 --- /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 4d656c28f..6e5712ada 100644 --- a/src/OpenSHC/Map/Navigation/PathFindingState/updatePathLinkageLayerForEachBuildingAtEachTile.cpp +++ b/src/OpenSHC/Map/Navigation/PathFindingState/updatePathLinkageLayerForEachBuildingAtEachTile.cpp @@ -1,4 +1,4 @@ -#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" +#include "../PathFindingState.func.hpp" #include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" diff --git a/src/OpenSHC/Map/Navigation/PathFindingState/updatePathLinkageTileMapRelatedToGates.cpp b/src/OpenSHC/Map/Navigation/PathFindingState/updatePathLinkageTileMapRelatedToGates.cpp new file mode 100644 index 000000000..bc0164f09 --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/updatePathLinkageTileMapRelatedToGates.cpp @@ -0,0 +1,122 @@ +#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 iVar2; + int iVar3; + int _anotherTile; + int iVar4; + int _middleTileUnk; + uint uVar5; + int _xMiddleUnk; + int _pl2; + uint _widthOrHeight; + _middleTileUnk = (int)(short)DAT_BuildingsState::instance.buildings[buildingID].x; + _widthOrHeight = DAT_BuildingsState::instance.buildings[buildingID].widthOrHeight; + int _half = (int)_widthOrHeight / 2; + if (DAT_BuildingsState::instance.buildings[buildingID].buildingVariation == 80) { + 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; + _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; + 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 000000000..fe0f71416 --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/updatePathLinkageTileMapRelatedToKeeps.cpp @@ -0,0 +1,66 @@ +#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) + { + uint uVar2; + int iVar3; + int iVar4; + short _orientation; + _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 { + 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 000000000..6093446b1 --- /dev/null +++ b/src/OpenSHC/Map/Navigation/PathFindingState/updatePathLinkageTileMapRelatedToSiegeTower.cpp @@ -0,0 +1,52 @@ +#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 iVar2; + int iVar3; + int iVar4; + int iVar5; + iVar4 = (int)(short)DAT_BuildingsState::instance.buildings[param_1].x; + iVar2 = (int)(short)DAT_BuildingsState::instance.buildings[param_1].y; + 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; + 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 000000000..3fd877cea --- /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 000000000..7e0c644f8 --- /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 000000000..c32e9fc1b --- /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 000000000..d7419acb3 --- /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 000000000..8b3c282dc --- /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; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index f6e47278b..971b1dee4 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -381,15 +381,15 @@ SHC_3BB0A8C1_0x00400260 | 0.0% | Pending SHC_3BB0A8C1_0x00400288 | 0.0% | Pending -SHC_3BB0A8C1_0x00401000 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00401000 | 0.0% | Pending -SHC_3BB0A8C1_0x00401040 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00401040 | 0.0% | Pending -SHC_3BB0A8C1_0x00401060 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00401060 | 0.0% | Pending -SHC_3BB0A8C1_0x00401090 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00401090 | 0.0% | Pending -SHC_3BB0A8C1_0x004010B0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004010B0 | 0.0% | Pending SHC_3BB0A8C1_0x004010E0 | 0.0% | Pending @@ -415,13 +415,13 @@ SHC_3BB0A8C1_0x004012F0 | 0.0% | Pending SHC_3BB0A8C1_0x00401380 | 0.0% | Pending -SHC_3BB0A8C1_0x00401400 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00401400 | 0.0% | Pending -SHC_3BB0A8C1_0x00401430 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00401430 | 0.0% | Pending SHC_3BB0A8C1_0x00401460 | 0.0% | Pending -SHC_3BB0A8C1_0x00401540 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00401540 | 0.0% | Pending SHC_3BB0A8C1_0x00401570 | 0.0% | Pending @@ -445,11 +445,11 @@ SHC_3BB0A8C1_0x004019D0 | 0.0% | Pending SHC_3BB0A8C1_0x00401A50 | 0.0% | Pending -SHC_3BB0A8C1_0x00401AE0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00401AE0 | 0.0% | Pending SHC_3BB0A8C1_0x00401B20 | 0.0% | Pending -SHC_3BB0A8C1_0x00401B60 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00401B60 | 0.0% | Pending SHC_3BB0A8C1_0x00401BA0 | 0.0% | Pending @@ -503,7 +503,7 @@ SHC_3BB0A8C1_0x00402A18 | 0.0% | Pending SHC_3BB0A8C1_0x00402A20 | 0.0% | Pending -SHC_3BB0A8C1_0x00402AB0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00402AB0 | 0.0% | Pending SHC_3BB0A8C1_0x00402AE0 | 0.0% | Pending @@ -531,7 +531,7 @@ SHC_3BB0A8C1_0x004036F0 | 0.0% | Pending SHC_3BB0A8C1_0x00403790 | 0.0% | Pending -SHC_3BB0A8C1_0x004038A0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004038A0 | 0.0% | Pending SHC_3BB0A8C1_0x004038B0 | 0.0% | Pending @@ -539,9 +539,9 @@ SHC_3BB0A8C1_0x00403900 | 0.0% | Pending SHC_3BB0A8C1_0x00403980 | 0.0% | Pending -SHC_3BB0A8C1_0x004039B0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004039B0 | 0.0% | Pending -SHC_3BB0A8C1_0x004039F0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004039F0 | 0.0% | Pending SHC_3BB0A8C1_0x00403A20 | 0.0% | Pending @@ -2347,9 +2347,9 @@ SHC_3BB0A8C1_0x00406900 | 0.0% | Pending SHC_3BB0A8C1_0x00406FD0 | 0.0% | Pending -SHC_3BB0A8C1_0x00407130 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00407130 | 0.0% | Pending -SHC_3BB0A8C1_0x00407160 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00407160 | 0.0% | Pending SHC_3BB0A8C1_0x00407190 | 0.0% | Pending @@ -2597,11 +2597,11 @@ SHC_3BB0A8C1_0x00409200 | 0.0% | Pending SHC_3BB0A8C1_0x004092B0 | 0.0% | Pending -SHC_3BB0A8C1_0x004092C0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004092C0 | 0.0% | Pending -SHC_3BB0A8C1_0x004092E0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004092E0 | 0.0% | Pending -SHC_3BB0A8C1_0x00409300 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00409300 | 0.0% | Pending SHC_3BB0A8C1_0x00409330 | 0.0% | Pending @@ -5543,15 +5543,15 @@ SHC_3BB0A8C1_0x00417B90 | 0.0% | Pending SHC_3BB0A8C1_0x00417FD0 | 0.0% | Pending -SHC_3BB0A8C1_0x004180E0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004180E0 | 0.0% | Pending SHC_3BB0A8C1_0x00418100 | 0.0% | Pending -SHC_3BB0A8C1_0x004184A0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004184A0 | 0.0% | Pending -SHC_3BB0A8C1_0x004184D0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004184D0 | 0.0% | Pending -SHC_3BB0A8C1_0x00418500 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00418500 | 0.0% | Pending SHC_3BB0A8C1_0x00418530 | 0.0% | Pending @@ -5559,9 +5559,9 @@ SHC_3BB0A8C1_0x00418640 | 0.0% | Pending SHC_3BB0A8C1_0x00418740 | 0.0% | Pending -SHC_3BB0A8C1_0x00418880 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00418880 | 0.0% | Pending -SHC_3BB0A8C1_0x004188C0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004188C0 | 0.0% | Pending SHC_3BB0A8C1_0x00418900 | 0.0% | Pending @@ -5575,7 +5575,7 @@ SHC_3BB0A8C1_0x00418C80 | 0.0% | Pending SHC_3BB0A8C1_0x00418EC0 | 0.0% | Pending -SHC_3BB0A8C1_0x00418F70 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00418F70 | 0.0% | Pending SHC_3BB0A8C1_0x00418F90 | 0.0% | Pending @@ -5585,7 +5585,7 @@ SHC_3BB0A8C1_0x00419190 | 0.0% | Pending SHC_3BB0A8C1_0x00419290 | 0.0% | Pending -SHC_3BB0A8C1_0x00419340 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00419340 | 0.0% | Pending SHC_3BB0A8C1_0x00419370 | 0.0% | Pending @@ -5817,13 +5817,13 @@ SHC_3BB0A8C1_0x00419EB0 | 0.0% | Pending SHC_3BB0A8C1_0x00419FA0 | 0.0% | Pending -SHC_3BB0A8C1_0x0041A060 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x0041A060 | 0.0% | Pending -SHC_3BB0A8C1_0x0041A0A0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x0041A0A0 | 0.0% | Pending SHC_3BB0A8C1_0x0041A0B0 | 0.0% | Pending -SHC_3BB0A8C1_0x0041A0D0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x0041A0D0 | 0.0% | Pending SHC_3BB0A8C1_0x0041A100 | 0.0% | Pending @@ -6043,17 +6043,17 @@ SHC_3BB0A8C1_0x0041A2AE | 0.0% | Pending SHC_3BB0A8C1_0x0041A2AF | 0.0% | Pending -SHC_3BB0A8C1_0x0041A2B0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x0041A2B0 | 0.0% | Pending SHC_3BB0A8C1_0x0041A2E0 | 0.0% | Pending SHC_3BB0A8C1_0x0041A340 | 0.0% | Pending -SHC_3BB0A8C1_0x0041A390 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x0041A390 | 0.0% | Pending -SHC_3BB0A8C1_0x0041A3C0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x0041A3C0 | 0.0% | Pending -SHC_3BB0A8C1_0x0041A3F0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x0041A3F0 | 0.0% | Pending SHC_3BB0A8C1_0x0041A420 | 0.0% | Pending @@ -6061,17 +6061,17 @@ SHC_3BB0A8C1_0x0041A460 | 0.0% | Pending SHC_3BB0A8C1_0x0041A520 | 0.0% | Pending -SHC_3BB0A8C1_0x0041A5C0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x0041A5C0 | 0.0% | Pending -SHC_3BB0A8C1_0x0041A5F0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x0041A5F0 | 0.0% | Pending -SHC_3BB0A8C1_0x0041A620 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x0041A620 | 0.0% | Pending SHC_3BB0A8C1_0x0041A650 | 0.0% | Pending SHC_3BB0A8C1_0x0041A680 | 0.0% | Pending -SHC_3BB0A8C1_0x0041A710 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x0041A710 | 0.0% | Pending SHC_3BB0A8C1_0x0041A740 | 100.0% | Reimplemented @@ -6657,13 +6657,13 @@ SHC_3BB0A8C1_0x00424680 | 0.0% | Pending SHC_3BB0A8C1_0x004246B0 | 0.0% | Pending -SHC_3BB0A8C1_0x004246E0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004246E0 | 0.0% | Pending SHC_3BB0A8C1_0x00424700 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00424720 | 0.0% | Pending -SHC_3BB0A8C1_0x00424770 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00424770 | 0.0% | Pending SHC_3BB0A8C1_0x004247A0 | 0.0% | Pending @@ -6675,7 +6675,7 @@ SHC_3BB0A8C1_0x00424AD0 | 0.0% | Pending SHC_3BB0A8C1_0x00424B10 | 0.0% | Pending -SHC_3BB0A8C1_0x00424BD0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00424BD0 | 0.0% | Pending SHC_3BB0A8C1_0x00424BE0 | 0.0% | Pending @@ -6769,7 +6769,7 @@ SHC_3BB0A8C1_0x00426570 | 0.0% | Pending SHC_3BB0A8C1_0x00426600 | 0.0% | Pending -SHC_3BB0A8C1_0x004266A0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004266A0 | 0.0% | Pending SHC_3BB0A8C1_0x004266E0 | 0.0% | Pending @@ -6793,7 +6793,7 @@ SHC_3BB0A8C1_0x00426D30 | 0.0% | Pending SHC_3BB0A8C1_0x00426ED0 | 0.0% | Pending -SHC_3BB0A8C1_0x00426F80 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00426F80 | 0.0% | Pending SHC_3BB0A8C1_0x00426FB0 | 0.0% | Pending @@ -6803,9 +6803,9 @@ SHC_3BB0A8C1_0x00427110 | 0.0% | Pending SHC_3BB0A8C1_0x00427180 | 0.0% | Pending -SHC_3BB0A8C1_0x004271E0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004271E0 | 0.0% | Pending -SHC_3BB0A8C1_0x00427210 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00427210 | 0.0% | Pending SHC_3BB0A8C1_0x00427240 | 0.0% | Pending @@ -6867,7 +6867,7 @@ SHC_3BB0A8C1_0x00428480 | 0.0% | Pending SHC_3BB0A8C1_0x00428590 | 0.0% | Pending -SHC_3BB0A8C1_0x004285C0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004285C0 | 0.0% | Pending SHC_3BB0A8C1_0x004285F0 | 0.0% | Pending @@ -6891,7 +6891,7 @@ SHC_3BB0A8C1_0x00428A60 | 0.0% | Pending SHC_3BB0A8C1_0x00428AC0 | 0.0% | Pending -SHC_3BB0A8C1_0x00429630 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00429630 | 0.0% | Pending SHC_3BB0A8C1_0x00429650 | 0.0% | Pending @@ -6973,9 +6973,9 @@ SHC_3BB0A8C1_0x0042AC34 | 0.0% | Pending SHC_3BB0A8C1_0x0042AC38 | 0.0% | Pending -SHC_3BB0A8C1_0x0042AC40 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x0042AC40 | 0.0% | Pending -SHC_3BB0A8C1_0x0042AC60 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x0042AC60 | 0.0% | Pending SHC_3BB0A8C1_0x0042AC70 | 0.0% | Pending @@ -7443,7 +7443,7 @@ SHC_3BB0A8C1_0x0042B960 | 0.0% | Pending SHC_3BB0A8C1_0x0042BA50 | 0.0% | Pending -SHC_3BB0A8C1_0x0042BB70 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x0042BB70 | 0.0% | Pending SHC_3BB0A8C1_0x0042BB90 | 0.0% | Pending @@ -7453,7 +7453,7 @@ SHC_3BB0A8C1_0x0042BF00 | 0.0% | Pending SHC_3BB0A8C1_0x0042BFC0 | 0.0% | Pending -SHC_3BB0A8C1_0x0042C060 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x0042C060 | 0.0% | Pending SHC_3BB0A8C1_0x0042C090 | 0.0% | Pending @@ -8719,7 +8719,7 @@ SHC_3BB0A8C1_0x0042EF78 | 0.0% | Pending SHC_3BB0A8C1_0x0042EF80 | 0.0% | Pending -SHC_3BB0A8C1_0x0042EFE0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x0042EFE0 | 0.0% | Pending SHC_3BB0A8C1_0x0042F010 | 0.0% | Pending @@ -8741,7 +8741,7 @@ SHC_3BB0A8C1_0x0042F3BC | 0.0% | Pending SHC_3BB0A8C1_0x0042F3C0 | 0.0% | Pending -SHC_3BB0A8C1_0x0042F3D0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x0042F3D0 | 0.0% | Pending SHC_3BB0A8C1_0x0042F3F0 | 0.0% | Pending @@ -9163,7 +9163,7 @@ SHC_3BB0A8C1_0x0042F940 | 0.0% | Pending SHC_3BB0A8C1_0x0042FA10 | 0.0% | Pending -SHC_3BB0A8C1_0x0042FAA0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x0042FAA0 | 0.0% | Pending SHC_3BB0A8C1_0x0042FAC0 | 0.0% | Pending @@ -10535,7 +10535,7 @@ SHC_3BB0A8C1_0x00430BF0 | 0.0% | Pending SHC_3BB0A8C1_0x00430CB8 | 0.0% | Pending -SHC_3BB0A8C1_0x00430CC0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00430CC0 | 0.0% | Pending SHC_3BB0A8C1_0x00430CE0 | 0.0% | Pending @@ -11083,9 +11083,9 @@ SHC_3BB0A8C1_0x00431B60 | 0.0% | Pending SHC_3BB0A8C1_0x00433030 | 0.0% | Pending -SHC_3BB0A8C1_0x00433200 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00433200 | 0.0% | Pending -SHC_3BB0A8C1_0x00433230 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00433230 | 0.0% | Pending SHC_3BB0A8C1_0x00433260 | 0.0% | Pending @@ -11099,7 +11099,7 @@ SHC_3BB0A8C1_0x00433558 | 0.0% | Pending SHC_3BB0A8C1_0x0043355C | 0.0% | Pending -SHC_3BB0A8C1_0x00433560 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00433560 | 0.0% | Pending SHC_3BB0A8C1_0x004335A0 | 0.0% | Pending @@ -11135,9 +11135,9 @@ SHC_3BB0A8C1_0x00434224 | 0.0% | Pending SHC_3BB0A8C1_0x00434228 | 0.0% | Pending -SHC_3BB0A8C1_0x00434230 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00434230 | 0.0% | Pending -SHC_3BB0A8C1_0x00434260 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00434260 | 0.0% | Pending SHC_3BB0A8C1_0x00434270 | 0.0% | Pending @@ -13357,7 +13357,7 @@ SHC_3BB0A8C1_0x0043937C | 0.0% | Pending SHC_3BB0A8C1_0x00439380 | 0.0% | Pending -SHC_3BB0A8C1_0x00439390 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00439390 | 0.0% | Pending SHC_3BB0A8C1_0x004393C0 | 0.0% | Pending @@ -13389,19 +13389,19 @@ SHC_3BB0A8C1_0x00439724 | 0.0% | Pending SHC_3BB0A8C1_0x00439730 | 0.0% | Pending -SHC_3BB0A8C1_0x00439890 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00439890 | 0.0% | Pending SHC_3BB0A8C1_0x004398B0 | 0.0% | Pending -SHC_3BB0A8C1_0x0043A850 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x0043A850 | 0.0% | Pending -SHC_3BB0A8C1_0x0043A860 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x0043A860 | 0.0% | Pending -SHC_3BB0A8C1_0x0043A880 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x0043A880 | 0.0% | Pending -SHC_3BB0A8C1_0x0043A8C0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x0043A8C0 | 0.0% | Pending -SHC_3BB0A8C1_0x0043A8D0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x0043A8D0 | 0.0% | Pending SHC_3BB0A8C1_0x0043A8E0 | 0.0% | Pending @@ -13595,9 +13595,9 @@ SHC_3BB0A8C1_0x0043E5F0 | 0.0% | Pending SHC_3BB0A8C1_0x0043E6C0 | 0.0% | Pending -SHC_3BB0A8C1_0x0043F2B0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x0043F2B0 | 0.0% | Pending -SHC_3BB0A8C1_0x0043F2C0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x0043F2C0 | 0.0% | Pending SHC_3BB0A8C1_0x0043F2F0 | 0.0% | Pending @@ -13611,9 +13611,9 @@ SHC_3BB0A8C1_0x0043FBB0 | 0.0% | Pending SHC_3BB0A8C1_0x0043FBF0 | 0.0% | Pending -SHC_3BB0A8C1_0x0043FC80 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x0043FC80 | 0.0% | Pending -SHC_3BB0A8C1_0x0043FCA0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x0043FCA0 | 0.0% | Pending SHC_3BB0A8C1_0x0043FCB0 | 0.0% | Pending @@ -13631,13 +13631,13 @@ SHC_3BB0A8C1_0x00440280 | 0.0% | Pending SHC_3BB0A8C1_0x00440360 | 0.0% | Pending -SHC_3BB0A8C1_0x004403D0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004403D0 | 0.0% | Pending -SHC_3BB0A8C1_0x00440400 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00440400 | 0.0% | Pending -SHC_3BB0A8C1_0x00440410 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00440410 | 0.0% | Pending -SHC_3BB0A8C1_0x00440420 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00440420 | 0.0% | Pending SHC_3BB0A8C1_0x00440430 | 0.0% | Pending @@ -16649,11 +16649,11 @@ SHC_3BB0A8C1_0x0044A720 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0044A830 | 0.0% | Pending -SHC_3BB0A8C1_0x0044AA70 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x0044AA70 | 0.0% | Pending -SHC_3BB0A8C1_0x0044AA80 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x0044AA80 | 0.0% | Pending -SHC_3BB0A8C1_0x0044AAA0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x0044AAA0 | 0.0% | Pending SHC_3BB0A8C1_0x0044AAB0 | 100.0% | Reimplemented @@ -16867,7 +16867,7 @@ SHC_3BB0A8C1_0x0044B680 | 0.0% | Pending SHC_3BB0A8C1_0x0044B760 | 0.0% | Pending -SHC_3BB0A8C1_0x0044B7D0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x0044B7D0 | 0.0% | Pending SHC_3BB0A8C1_0x0044B800 | 0.0% | Pending @@ -16915,17 +16915,17 @@ SHC_3BB0A8C1_0x0044CBE0 | 0.0% | Pending SHC_3BB0A8C1_0x0044CC30 | 0.0% | Pending -SHC_3BB0A8C1_0x0044CCA0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x0044CCA0 | 0.0% | Pending -SHC_3BB0A8C1_0x0044CCC0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x0044CCC0 | 0.0% | Pending -SHC_3BB0A8C1_0x0044CCD0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x0044CCD0 | 0.0% | Pending -SHC_3BB0A8C1_0x0044CCF0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x0044CCF0 | 0.0% | Pending -SHC_3BB0A8C1_0x0044CD10 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x0044CD10 | 0.0% | Pending -SHC_3BB0A8C1_0x0044CD30 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x0044CD30 | 0.0% | Pending SHC_3BB0A8C1_0x0044CD40 | 0.0% | Pending @@ -16979,15 +16979,15 @@ SHC_3BB0A8C1_0x00454700 | 0.0% | Pending SHC_3BB0A8C1_0x004547C0 | 0.0% | Pending -SHC_3BB0A8C1_0x004548D0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004548D0 | 0.0% | Pending SHC_3BB0A8C1_0x00454900 | 0.0% | Pending -SHC_3BB0A8C1_0x00454960 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00454960 | 0.0% | Pending -SHC_3BB0A8C1_0x00454990 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00454990 | 0.0% | Pending -SHC_3BB0A8C1_0x004549C0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004549C0 | 0.0% | Pending SHC_3BB0A8C1_0x004549F0 | 0.0% | Pending @@ -16999,21 +16999,21 @@ SHC_3BB0A8C1_0x00454CE0 | 0.0% | Pending SHC_3BB0A8C1_0x00454D20 | 0.0% | Pending -SHC_3BB0A8C1_0x00454EE0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00454EE0 | 0.0% | Pending -SHC_3BB0A8C1_0x00454EF0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00454EF0 | 0.0% | Pending SHC_3BB0A8C1_0x00454F00 | 0.0% | Pending SHC_3BB0A8C1_0x00455050 | 0.0% | Pending -SHC_3BB0A8C1_0x00455250 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00455250 | 0.0% | Pending -SHC_3BB0A8C1_0x00455270 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00455270 | 0.0% | Pending SHC_3BB0A8C1_0x00455290 | 0.0% | Pending -SHC_3BB0A8C1_0x004552E0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004552E0 | 0.0% | Pending SHC_3BB0A8C1_0x00455300 | 0.0% | Pending @@ -17045,7 +17045,7 @@ SHC_3BB0A8C1_0x00455E40 | 0.0% | Pending SHC_3BB0A8C1_0x004560F0 | 0.0% | Pending -SHC_3BB0A8C1_0x004563B0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004563B0 | 0.0% | Pending SHC_3BB0A8C1_0x004563D0 | 0.0% | Pending @@ -17669,7 +17669,7 @@ SHC_3BB0A8C1_0x00457A70 | 0.0% | Pending SHC_3BB0A8C1_0x00457AD0 | 0.0% | Pending -SHC_3BB0A8C1_0x00457B40 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00457B40 | 0.0% | Pending SHC_3BB0A8C1_0x00457B80 | 0.0% | Pending @@ -17693,15 +17693,15 @@ SHC_3BB0A8C1_0x004585B0 | 0.0% | Pending SHC_3BB0A8C1_0x004585F0 | 0.0% | Pending -SHC_3BB0A8C1_0x004586D0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004586D0 | 0.0% | Pending SHC_3BB0A8C1_0x004586F0 | 0.0% | Pending -SHC_3BB0A8C1_0x00458700 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00458700 | 0.0% | Pending SHC_3BB0A8C1_0x00458720 | 0.0% | Pending -SHC_3BB0A8C1_0x00458740 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00458740 | 0.0% | Pending SHC_3BB0A8C1_0x00458760 | 0.0% | Pending @@ -17713,13 +17713,13 @@ SHC_3BB0A8C1_0x00458820 | 0.0% | Pending SHC_3BB0A8C1_0x00458840 | 0.0% | Pending -SHC_3BB0A8C1_0x00458890 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00458890 | 0.0% | Pending SHC_3BB0A8C1_0x004588A0 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x004588D0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004588D0 | 0.0% | Pending -SHC_3BB0A8C1_0x004588F0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004588F0 | 0.0% | Pending SHC_3BB0A8C1_0x00458910 | 100.0% | Reimplemented @@ -17757,11 +17757,11 @@ SHC_3BB0A8C1_0x00458F70 | 0.0% | Pending SHC_3BB0A8C1_0x00459080 | 0.0% | Pending -SHC_3BB0A8C1_0x00459140 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00459140 | 0.0% | Pending -SHC_3BB0A8C1_0x00459170 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00459170 | 0.0% | Pending -SHC_3BB0A8C1_0x004591B0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004591B0 | 0.0% | Pending SHC_3BB0A8C1_0x004591F0 | 0.0% | Pending @@ -17889,7 +17889,7 @@ SHC_3BB0A8C1_0x004595D0 | 0.0% | Pending SHC_3BB0A8C1_0x00459640 | 0.0% | Pending -SHC_3BB0A8C1_0x004596D0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004596D0 | 0.0% | Pending SHC_3BB0A8C1_0x00459700 | 0.0% | Pending @@ -17907,9 +17907,9 @@ SHC_3BB0A8C1_0x00459A40 | 0.0% | Pending SHC_3BB0A8C1_0x00459B50 | 0.0% | Pending -SHC_3BB0A8C1_0x00459BB0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00459BB0 | 0.0% | Pending -SHC_3BB0A8C1_0x00459BE0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00459BE0 | 0.0% | Pending SHC_3BB0A8C1_0x00459BF0 | 0.0% | Pending @@ -18025,7 +18025,7 @@ SHC_3BB0A8C1_0x0045AE70 | 0.0% | Pending SHC_3BB0A8C1_0x0045AEB0 | 0.0% | Pending -SHC_3BB0A8C1_0x0045AF00 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x0045AF00 | 0.0% | Pending SHC_3BB0A8C1_0x0045AF30 | 0.0% | Pending @@ -18035,13 +18035,13 @@ SHC_3BB0A8C1_0x0045B3A0 | 0.0% | Pending SHC_3BB0A8C1_0x0045B3E0 | 0.0% | Pending -SHC_3BB0A8C1_0x0045B460 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x0045B460 | 0.0% | Pending SHC_3BB0A8C1_0x0045B4A0 | 0.0% | Pending SHC_3BB0A8C1_0x0045B6B0 | 0.0% | Pending -SHC_3BB0A8C1_0x0045B7F0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x0045B7F0 | 0.0% | Pending SHC_3BB0A8C1_0x0045B830 | 0.0% | Pending @@ -18145,11 +18145,11 @@ SHC_3BB0A8C1_0x0045CA20 | 0.0% | Pending SHC_3BB0A8C1_0x0045CD10 | 0.0% | Pending -SHC_3BB0A8C1_0x0045D060 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x0045D060 | 0.0% | Pending SHC_3BB0A8C1_0x0045D080 | 0.0% | Pending -SHC_3BB0A8C1_0x0045D0B0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x0045D0B0 | 0.0% | Pending SHC_3BB0A8C1_0x0045D0C0 | 0.0% | Pending @@ -18747,7 +18747,7 @@ SHC_3BB0A8C1_0x0045F0CD | 0.0% | Pending SHC_3BB0A8C1_0x0045F0D0 | 0.0% | Pending -SHC_3BB0A8C1_0x0045F120 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x0045F120 | 0.0% | Pending SHC_3BB0A8C1_0x0045F130 | 0.0% | Pending @@ -19153,7 +19153,7 @@ SHC_3BB0A8C1_0x00462FE0 | 0.0% | Pending SHC_3BB0A8C1_0x00462FF0 | 0.0% | Pending -SHC_3BB0A8C1_0x004630B0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004630B0 | 0.0% | Pending SHC_3BB0A8C1_0x004630D0 | 0.0% | Pending @@ -19843,11 +19843,11 @@ SHC_3BB0A8C1_0x00464856 | 0.0% | Pending SHC_3BB0A8C1_0x00464860 | 0.0% | Pending -SHC_3BB0A8C1_0x004649C0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004649C0 | 0.0% | Pending SHC_3BB0A8C1_0x004649D0 | 0.0% | Pending -SHC_3BB0A8C1_0x00464D90 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00464D90 | 0.0% | Pending SHC_3BB0A8C1_0x00464DA0 | 0.0% | Pending @@ -19857,19 +19857,19 @@ SHC_3BB0A8C1_0x00464EF0 | 0.0% | Pending SHC_3BB0A8C1_0x00465040 | 0.0% | Pending -SHC_3BB0A8C1_0x00465080 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00465080 | 0.0% | Pending -SHC_3BB0A8C1_0x004650A0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004650A0 | 0.0% | Pending -SHC_3BB0A8C1_0x004650C0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004650C0 | 0.0% | Pending -SHC_3BB0A8C1_0x004650F0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004650F0 | 0.0% | Pending SHC_3BB0A8C1_0x00465110 | 0.0% | Pending SHC_3BB0A8C1_0x00465200 | 0.0% | Pending -SHC_3BB0A8C1_0x004652A0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004652A0 | 0.0% | Pending SHC_3BB0A8C1_0x004652D0 | 0.0% | Pending @@ -19905,15 +19905,15 @@ SHC_3BB0A8C1_0x00465700 | 0.0% | Pending SHC_3BB0A8C1_0x004657B0 | 0.0% | Pending -SHC_3BB0A8C1_0x00465800 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00465800 | 0.0% | Pending SHC_3BB0A8C1_0x00465820 | 0.0% | Pending -SHC_3BB0A8C1_0x00465890 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00465890 | 0.0% | Pending SHC_3BB0A8C1_0x004658B0 | 0.0% | Pending -SHC_3BB0A8C1_0x00465920 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00465920 | 0.0% | Pending SHC_3BB0A8C1_0x00465950 | 0.0% | Pending @@ -19929,7 +19929,7 @@ SHC_3BB0A8C1_0x00465F20 | 0.0% | Pending SHC_3BB0A8C1_0x00465F90 | 0.0% | Pending -SHC_3BB0A8C1_0x004660B0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004660B0 | 0.0% | Pending SHC_3BB0A8C1_0x004660F0 | 0.0% | Pending @@ -19945,7 +19945,7 @@ SHC_3BB0A8C1_0x00466480 | 0.0% | Pending SHC_3BB0A8C1_0x00466620 | 0.0% | Pending -SHC_3BB0A8C1_0x00466710 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00466710 | 0.0% | Pending SHC_3BB0A8C1_0x00466730 | 0.0% | Pending @@ -19975,9 +19975,9 @@ SHC_3BB0A8C1_0x004668E0 | 0.0% | Pending SHC_3BB0A8C1_0x004668E4 | 0.0% | Pending -SHC_3BB0A8C1_0x004668F0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004668F0 | 0.0% | Pending -SHC_3BB0A8C1_0x00466920 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00466920 | 0.0% | Pending SHC_3BB0A8C1_0x00466950 | 0.0% | Pending @@ -19987,9 +19987,9 @@ SHC_3BB0A8C1_0x00466C20 | 0.0% | Pending SHC_3BB0A8C1_0x00466D10 | 0.0% | Pending -SHC_3BB0A8C1_0x00466E00 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00466E00 | 0.0% | Pending -SHC_3BB0A8C1_0x00466E10 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00466E10 | 0.0% | Pending SHC_3BB0A8C1_0x00466E20 | 0.0% | Pending @@ -20051,7 +20051,7 @@ SHC_3BB0A8C1_0x00467E04 | 0.0% | Pending SHC_3BB0A8C1_0x00467E26 | 0.0% | Pending -SHC_3BB0A8C1_0x00467E40 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00467E40 | 0.0% | Pending SHC_3BB0A8C1_0x00467E50 | 0.0% | Pending @@ -20059,31 +20059,31 @@ SHC_3BB0A8C1_0x00467EC0 | 0.0% | Pending SHC_3BB0A8C1_0x00467F50 | 0.0% | Pending -SHC_3BB0A8C1_0x00467F60 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00467F60 | 0.0% | Pending -SHC_3BB0A8C1_0x00467F80 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00467F80 | 0.0% | Pending -SHC_3BB0A8C1_0x00468030 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00468030 | 0.0% | Pending -SHC_3BB0A8C1_0x004680B0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004680B0 | 0.0% | Pending -SHC_3BB0A8C1_0x004680C0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004680C0 | 0.0% | Pending -SHC_3BB0A8C1_0x00468100 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00468100 | 0.0% | Pending -SHC_3BB0A8C1_0x00468370 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00468370 | 0.0% | Pending -SHC_3BB0A8C1_0x00468420 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00468420 | 0.0% | Pending -SHC_3BB0A8C1_0x004684D0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004684D0 | 0.0% | Pending -SHC_3BB0A8C1_0x00468590 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00468590 | 0.0% | Pending -SHC_3BB0A8C1_0x004685C0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004685C0 | 0.0% | Pending -SHC_3BB0A8C1_0x004687F0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004687F0 | 0.0% | Pending -SHC_3BB0A8C1_0x004689D0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004689D0 | 0.0% | Pending SHC_3BB0A8C1_0x00468A10 | 100.0% | Reimplemented @@ -20097,7 +20097,7 @@ SHC_3BB0A8C1_0x00468C30 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00468C40 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x00468C50 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00468C50 | 0.0% | Pending SHC_3BB0A8C1_0x00468C80 | 0.0% | Pending @@ -20149,19 +20149,19 @@ SHC_3BB0A8C1_0x00469980 | 0.0% | Pending SHC_3BB0A8C1_0x004699E0 | 0.0% | Pending -SHC_3BB0A8C1_0x00469A30 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00469A30 | 0.0% | Pending -SHC_3BB0A8C1_0x00469A70 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00469A70 | 0.0% | Pending SHC_3BB0A8C1_0x00469AD0 | 0.0% | Pending -SHC_3BB0A8C1_0x00469B90 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00469B90 | 0.0% | Pending SHC_3BB0A8C1_0x00469BE0 | 0.0% | Pending -SHC_3BB0A8C1_0x00469C40 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00469C40 | 0.0% | Pending -SHC_3BB0A8C1_0x00469E10 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00469E10 | 0.0% | Pending SHC_3BB0A8C1_0x00469E70 | 0.0% | Pending @@ -20729,25 +20729,25 @@ SHC_3BB0A8C1_0x0046AE80 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0046AEC0 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x0046B080 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x0046B080 | 0.0% | Pending -SHC_3BB0A8C1_0x0046B0D0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x0046B0D0 | 0.0% | Pending -SHC_3BB0A8C1_0x0046B110 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x0046B110 | 0.0% | Pending -SHC_3BB0A8C1_0x0046B140 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x0046B140 | 0.0% | Pending -SHC_3BB0A8C1_0x0046B170 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x0046B170 | 0.0% | Pending -SHC_3BB0A8C1_0x0046B1B0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x0046B1B0 | 0.0% | Pending SHC_3BB0A8C1_0x0046B1F0 | 0.0% | Pending -SHC_3BB0A8C1_0x0046B2F0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x0046B2F0 | 0.0% | Pending -SHC_3BB0A8C1_0x0046B300 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x0046B300 | 0.0% | Pending -SHC_3BB0A8C1_0x0046B320 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x0046B320 | 0.0% | Pending SHC_3BB0A8C1_0x0046B340 | 0.0% | Pending @@ -20893,7 +20893,7 @@ SHC_3BB0A8C1_0x0046BBD0 | 0.0% | Pending SHC_3BB0A8C1_0x0046BC90 | 0.0% | Pending -SHC_3BB0A8C1_0x0046BD20 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x0046BD20 | 0.0% | Pending SHC_3BB0A8C1_0x0046BD50 | 0.0% | Pending @@ -20945,7 +20945,7 @@ SHC_3BB0A8C1_0x0046CAA0 | 0.0% | Pending SHC_3BB0A8C1_0x0046CC80 | 0.0% | Pending -SHC_3BB0A8C1_0x0046CCD0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x0046CCD0 | 0.0% | Pending SHC_3BB0A8C1_0x0046CD30 | 100.0% | Reimplemented @@ -20967,11 +20967,11 @@ SHC_3BB0A8C1_0x0046CEAC | 0.0% | Pending SHC_3BB0A8C1_0x0046CEB0 | 0.0% | Pending -SHC_3BB0A8C1_0x0046CEC0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x0046CEC0 | 0.0% | Pending -SHC_3BB0A8C1_0x0046CED0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x0046CED0 | 0.0% | Pending -SHC_3BB0A8C1_0x0046CEF0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x0046CEF0 | 0.0% | Pending SHC_3BB0A8C1_0x0046CF10 | 0.0% | Pending @@ -21201,7 +21201,7 @@ SHC_3BB0A8C1_0x0046F690 | 0.0% | Pending SHC_3BB0A8C1_0x0046F6B0 | 0.0% | Pending -SHC_3BB0A8C1_0x0046F730 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x0046F730 | 0.0% | Pending SHC_3BB0A8C1_0x0046F750 | 0.0% | Pending @@ -21257,13 +21257,13 @@ SHC_3BB0A8C1_0x004707F0 | 0.0% | Pending SHC_3BB0A8C1_0x004708F0 | 0.0% | Pending -SHC_3BB0A8C1_0x004709B0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004709B0 | 0.0% | Pending -SHC_3BB0A8C1_0x00470A00 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00470A00 | 0.0% | Pending -SHC_3BB0A8C1_0x00470B30 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00470B30 | 0.0% | Pending -SHC_3BB0A8C1_0x00470BC0 | 100.0% | Reimplemented, requires SHC_3BB0A8C1_0x0046CCD0 to be active +SHC_3BB0A8C1_0x00470BC0 | 0.0% | Pending SHC_3BB0A8C1_0x00470E90 | 0.0% | Pending @@ -21293,9 +21293,9 @@ SHC_3BB0A8C1_0x00471570 | 0.0% | Pending SHC_3BB0A8C1_0x004715A0 | 0.0% | Pending -SHC_3BB0A8C1_0x00471610 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00471610 | 0.0% | Pending -SHC_3BB0A8C1_0x00471670 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00471670 | 0.0% | Pending SHC_3BB0A8C1_0x00471690 | 0.0% | Pending @@ -21327,11 +21327,11 @@ SHC_3BB0A8C1_0x004718C0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x004718F0 | 0.0% | Pending -SHC_3BB0A8C1_0x004719E0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004719E0 | 0.0% | Pending SHC_3BB0A8C1_0x00471A00 | 0.0% | Pending -SHC_3BB0A8C1_0x00471A80 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00471A80 | 0.0% | Pending SHC_3BB0A8C1_0x00471AA0 | 0.0% | Pending @@ -21415,7 +21415,7 @@ SHC_3BB0A8C1_0x00472950 | 0.0% | Pending SHC_3BB0A8C1_0x004729B0 | 0.0% | Pending -SHC_3BB0A8C1_0x00472A90 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00472A90 | 0.0% | Pending SHC_3BB0A8C1_0x00472B20 | 0.0% | Pending @@ -21429,21 +21429,21 @@ SHC_3BB0A8C1_0x00472CB0 | 0.0% | Pending SHC_3BB0A8C1_0x00472D00 | 0.0% | Pending -SHC_3BB0A8C1_0x00472D60 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00472D60 | 0.0% | Pending SHC_3BB0A8C1_0x00472DD0 | 0.0% | Pending -SHC_3BB0A8C1_0x00472EF0 | 55.0% | Severe Register Issues, seem functional, but can not be considered done +SHC_3BB0A8C1_0x00472EF0 | 0.0% | Pending -SHC_3BB0A8C1_0x00473300 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00473300 | 0.0% | Pending -SHC_3BB0A8C1_0x004733A0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004733A0 | 0.0% | Pending -SHC_3BB0A8C1_0x00473640 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00473640 | 0.0% | Pending -SHC_3BB0A8C1_0x004737B0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004737B0 | 0.0% | Pending -SHC_3BB0A8C1_0x00473830 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00473830 | 0.0% | Pending SHC_3BB0A8C1_0x00473870 | 0.0% | Pending @@ -22307,7 +22307,7 @@ SHC_3BB0A8C1_0x0047D0D8 | 0.0% | Pending SHC_3BB0A8C1_0x0047D0DC | 0.0% | Pending -SHC_3BB0A8C1_0x0047D0E0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x0047D0E0 | 0.0% | Pending SHC_3BB0A8C1_0x0047D100 | 0.0% | Pending @@ -22327,7 +22327,7 @@ SHC_3BB0A8C1_0x0047D3DC | 0.0% | Pending SHC_3BB0A8C1_0x0047D3E0 | 0.0% | Pending -SHC_3BB0A8C1_0x0047D3F0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x0047D3F0 | 0.0% | Pending SHC_3BB0A8C1_0x0047D410 | 0.0% | Pending @@ -22373,9 +22373,9 @@ SHC_3BB0A8C1_0x0047E5B0 | 0.0% | Pending SHC_3BB0A8C1_0x0047E5D0 | 0.0% | Pending -SHC_3BB0A8C1_0x0047E7E0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x0047E7E0 | 0.0% | Pending -SHC_3BB0A8C1_0x0047E800 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x0047E800 | 0.0% | Pending SHC_3BB0A8C1_0x0047E830 | 0.0% | Pending @@ -22393,7 +22393,7 @@ SHC_3BB0A8C1_0x0047EC10 | 0.0% | Pending SHC_3BB0A8C1_0x0047EDE0 | 0.0% | Pending -SHC_3BB0A8C1_0x0047EEB0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x0047EEB0 | 0.0% | Pending SHC_3BB0A8C1_0x0047EED0 | 0.0% | Pending @@ -22411,13 +22411,13 @@ SHC_3BB0A8C1_0x0047FD50 | 0.0% | Pending SHC_3BB0A8C1_0x0047FEA0 | 0.0% | Pending -SHC_3BB0A8C1_0x0047FFA0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x0047FFA0 | 0.0% | Pending SHC_3BB0A8C1_0x0047FFE0 | 0.0% | Pending SHC_3BB0A8C1_0x00480050 | 0.0% | Pending -SHC_3BB0A8C1_0x004800B0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004800B0 | 0.0% | Pending SHC_3BB0A8C1_0x004800E0 | 0.0% | Pending @@ -22425,7 +22425,7 @@ SHC_3BB0A8C1_0x00480210 | 0.0% | Pending SHC_3BB0A8C1_0x00480440 | 0.0% | Pending -SHC_3BB0A8C1_0x00480570 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00480570 | 0.0% | Pending SHC_3BB0A8C1_0x00480580 | 0.0% | Pending @@ -22547,7 +22547,7 @@ SHC_3BB0A8C1_0x004821D5 | 0.0% | Pending SHC_3BB0A8C1_0x004821E0 | 0.0% | Pending -SHC_3BB0A8C1_0x00482280 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00482280 | 0.0% | Pending SHC_3BB0A8C1_0x00482290 | 0.0% | Pending @@ -23167,7 +23167,7 @@ SHC_3BB0A8C1_0x0048BD40 | 0.0% | Pending SHC_3BB0A8C1_0x0048BD80 | 0.0% | Pending -SHC_3BB0A8C1_0x0048BF70 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x0048BF70 | 0.0% | Pending SHC_3BB0A8C1_0x0048BF80 | 0.0% | Pending @@ -23357,7 +23357,7 @@ SHC_3BB0A8C1_0x0048F841 | 0.0% | Pending SHC_3BB0A8C1_0x0048F842 | 0.0% | Pending -SHC_3BB0A8C1_0x0048F850 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x0048F850 | 0.0% | Pending SHC_3BB0A8C1_0x0048F870 | 0.0% | Pending @@ -23373,7 +23373,7 @@ SHC_3BB0A8C1_0x00490060 | 0.0% | Pending SHC_3BB0A8C1_0x00490080 | 0.0% | Pending -SHC_3BB0A8C1_0x00490340 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00490340 | 0.0% | Pending SHC_3BB0A8C1_0x00490380 | 0.0% | Pending @@ -23407,13 +23407,13 @@ SHC_3BB0A8C1_0x00491680 | 0.0% | Pending SHC_3BB0A8C1_0x004916C0 | 0.0% | Pending -SHC_3BB0A8C1_0x00491730 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00491730 | 0.0% | Pending SHC_3BB0A8C1_0x00491750 | 0.0% | Pending SHC_3BB0A8C1_0x004917C0 | 0.0% | Pending -SHC_3BB0A8C1_0x00491810 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00491810 | 0.0% | Pending SHC_3BB0A8C1_0x00491840 | 0.0% | Pending @@ -23421,9 +23421,9 @@ SHC_3BB0A8C1_0x00491A30 | 0.0% | Pending SHC_3BB0A8C1_0x00491AC0 | 0.0% | Pending -SHC_3BB0A8C1_0x00491BF0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00491BF0 | 0.0% | Pending -SHC_3BB0A8C1_0x00491C20 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00491C20 | 0.0% | Pending SHC_3BB0A8C1_0x00491C50 | 0.0% | Pending @@ -23431,7 +23431,7 @@ SHC_3BB0A8C1_0x00491CE0 | 0.0% | Pending SHC_3BB0A8C1_0x00491D70 | 0.0% | Pending -SHC_3BB0A8C1_0x00491E80 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00491E80 | 0.0% | Pending SHC_3BB0A8C1_0x00491EB0 | 0.0% | Pending @@ -23485,7 +23485,7 @@ SHC_3BB0A8C1_0x00492654 | 0.0% | Pending SHC_3BB0A8C1_0x00492658 | 0.0% | Pending -SHC_3BB0A8C1_0x00492660 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00492660 | 0.0% | Pending SHC_3BB0A8C1_0x00492690 | 0.0% | Pending @@ -23501,7 +23501,7 @@ SHC_3BB0A8C1_0x004929BC | 0.0% | Pending SHC_3BB0A8C1_0x004929C0 | 0.0% | Pending -SHC_3BB0A8C1_0x00492A60 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00492A60 | 0.0% | Pending SHC_3BB0A8C1_0x00492A90 | 0.0% | Pending @@ -23521,7 +23521,7 @@ SHC_3BB0A8C1_0x00492C58 | 0.0% | Pending SHC_3BB0A8C1_0x00492C5C | 0.0% | Pending -SHC_3BB0A8C1_0x00492C60 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00492C60 | 0.0% | Pending SHC_3BB0A8C1_0x00492C90 | 0.0% | Pending @@ -23629,7 +23629,7 @@ SHC_3BB0A8C1_0x00493690 | 0.0% | Pending SHC_3BB0A8C1_0x004937A4 | 0.0% | Pending -SHC_3BB0A8C1_0x004937B0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004937B0 | 0.0% | Pending SHC_3BB0A8C1_0x004937E0 | 0.0% | Pending @@ -24041,7 +24041,7 @@ SHC_3BB0A8C1_0x004941E7 | 0.0% | Pending SHC_3BB0A8C1_0x004941E8 | 0.0% | Pending -SHC_3BB0A8C1_0x004941F0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004941F0 | 0.0% | Pending SHC_3BB0A8C1_0x00494210 | 0.0% | Pending @@ -24111,7 +24111,7 @@ SHC_3BB0A8C1_0x004948BF | 0.0% | Pending SHC_3BB0A8C1_0x004948C0 | 0.0% | Pending -SHC_3BB0A8C1_0x00494920 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00494920 | 0.0% | Pending SHC_3BB0A8C1_0x00494950 | 0.0% | Pending @@ -24213,9 +24213,9 @@ SHC_3BB0A8C1_0x00495230 | 0.0% | Pending SHC_3BB0A8C1_0x004954A0 | 0.0% | Pending -SHC_3BB0A8C1_0x00495800 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00495800 | 0.0% | Pending -SHC_3BB0A8C1_0x00495840 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00495840 | 0.0% | Pending SHC_3BB0A8C1_0x00495860 | 0.0% | Pending @@ -24347,103 +24347,103 @@ SHC_3BB0A8C1_0x00496E20 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00496E30 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x00496E40 | 0.0% | Pending +SHC_3BB0A8C1_0x00496E40 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00496EA0 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x00496EC0 | 0.0% | Pending +SHC_3BB0A8C1_0x00496EC0 | 66.0% | hoist signed start-tile reads -SHC_3BB0A8C1_0x00496F90 | 0.0% | Pending +SHC_3BB0A8C1_0x00496F90 | 56.5% | row local for the y read, tie -SHC_3BB0A8C1_0x00497080 | 0.0% | Pending +SHC_3BB0A8C1_0x00497080 | 78.1% | hoist signed start-tile read -SHC_3BB0A8C1_0x00497180 | 0.0% | Pending +SHC_3BB0A8C1_0x00497180 | 97.1% | int locals for the 16-bit read -SHC_3BB0A8C1_0x00497280 | 0.0% | Pending +SHC_3BB0A8C1_0x00497280 | 55.8% | param_5 block out of line -SHC_3BB0A8C1_0x004974D0 | 0.0% | Pending +SHC_3BB0A8C1_0x004974D0 | 32.1% | statement order -SHC_3BB0A8C1_0x00497690 | 0.0% | Pending +SHC_3BB0A8C1_0x00497690 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x00497740 | 0.0% | Pending +SHC_3BB0A8C1_0x00497740 | 50.5% | statement order -SHC_3BB0A8C1_0x00497B80 | 0.0% | Pending +SHC_3BB0A8C1_0x00497B80 | 52.6% | statement order -SHC_3BB0A8C1_0x00498020 | 0.0% | Pending +SHC_3BB0A8C1_0x00498020 | 61.4% | counted direction loop, combin SHC_3BB0A8C1_0x00498170 | 0.0% | Pending -SHC_3BB0A8C1_0x00498400 | 0.0% | Pending +SHC_3BB0A8C1_0x00498400 | 49.8% | uniform unrolled bodies with d SHC_3BB0A8C1_0x004985D0 | 0.0% | Pending -SHC_3BB0A8C1_0x00498A40 | 0.0% | Pending +SHC_3BB0A8C1_0x00498A40 | 82.2% | fix off-by-one maxTries SHC_3BB0A8C1_0x00498B70 | 0.0% | Pending -SHC_3BB0A8C1_0x00498FD0 | 0.0% | Pending +SHC_3BB0A8C1_0x00498FD0 | 19.9% | flag init moved to the loop SHC_3BB0A8C1_0x004990F0 | 0.0% | Pending -SHC_3BB0A8C1_0x004995E0 | 0.0% | Pending +SHC_3BB0A8C1_0x004995E0 | 66.7% | counter guard split out SHC_3BB0A8C1_0x00499970 | 0.0% | Pending -SHC_3BB0A8C1_0x004999C0 | 0.0% | Pending +SHC_3BB0A8C1_0x004999C0 | 51.0% | comma expr expanded, tie -SHC_3BB0A8C1_0x00499DC0 | 0.0% | Pending +SHC_3BB0A8C1_0x00499DC0 | 67.1% | signed modulo and signed byte -SHC_3BB0A8C1_0x00499FA0 | 0.0% | Pending +SHC_3BB0A8C1_0x00499FA0 | 37.5% | Style pass, asm differs -SHC_3BB0A8C1_0x0049A1C0 | 0.0% | Pending +SHC_3BB0A8C1_0x0049A1C0 | 62.2% | tile locals per row -SHC_3BB0A8C1_0x0049A2E0 | 0.0% | Pending +SHC_3BB0A8C1_0x0049A2E0 | 96.3% | index locals + statement order -SHC_3BB0A8C1_0x0049A370 | 0.0% | Pending +SHC_3BB0A8C1_0x0049A370 | 12.5% | statement order -SHC_3BB0A8C1_0x0049A5E0 | 0.0% | Pending +SHC_3BB0A8C1_0x0049A5E0 | 78.3% | Style pass, asm differs SHC_3BB0A8C1_0x0049A610 | 0.0% | Pending -SHC_3BB0A8C1_0x0049A6D0 | 0.0% | Pending +SHC_3BB0A8C1_0x0049A6D0 | 72.5% | unsigned area read, matches mo SHC_3BB0A8C1_0x0049A800 | 0.0% | Pending -SHC_3BB0A8C1_0x0049AAD0 | 0.0% | Pending +SHC_3BB0A8C1_0x0049AAD0 | 87.1% | statement order SHC_3BB0A8C1_0x0049AC80 | 0.0% | Pending -SHC_3BB0A8C1_0x0049AF50 | 0.0% | Pending +SHC_3BB0A8C1_0x0049AF50 | 22.1% | statement order SHC_3BB0A8C1_0x0049B000 | 0.0% | Pending SHC_3BB0A8C1_0x0049B1C0 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x0049B1D0 | 0.0% | Pending +SHC_3BB0A8C1_0x0049B1D0 | 87.3% | statement order SHC_3BB0A8C1_0x0049B2B0 | 0.0% | Pending -SHC_3BB0A8C1_0x0049B5B0 | 0.0% | Pending +SHC_3BB0A8C1_0x0049B5B0 | 73.0% | unsigned building layer read SHC_3BB0A8C1_0x0049B6B0 | 0.0% | Pending SHC_3BB0A8C1_0x0049B8C0 | 0.0% | Pending -SHC_3BB0A8C1_0x0049B940 | 0.0% | Pending +SHC_3BB0A8C1_0x0049B940 | 86.5% | bound literal from the asm SHC_3BB0A8C1_0x0049BA30 | 0.0% | Pending SHC_3BB0A8C1_0x0049BA90 | 0.0% | Pending -SHC_3BB0A8C1_0x0049BBF0 | 0.0% | Pending +SHC_3BB0A8C1_0x0049BBF0 | 52.2% | statement order SHC_3BB0A8C1_0x0049BCD0 | 0.0% | Pending SHC_3BB0A8C1_0x0049BD40 | 0.0% | Pending -SHC_3BB0A8C1_0x0049BE60 | 0.0% | Pending +SHC_3BB0A8C1_0x0049BE60 | 51.6% | drop ghidra chkstk artifact st -SHC_3BB0A8C1_0x0049C020 | 0.0% | Pending +SHC_3BB0A8C1_0x0049C020 | 75.4% | start SHC_3BB0A8C1_0x0049C100 | 0.0% | Pending @@ -24655,93 +24655,93 @@ SHC_3BB0A8C1_0x0049C360 | 0.0% | Pending SHC_3BB0A8C1_0x0049C361 | 0.0% | Pending -SHC_3BB0A8C1_0x0049C370 | 0.0% | Pending +SHC_3BB0A8C1_0x0049C370 | 76.4% | Style pass, asm differs SHC_3BB0A8C1_0x0049C4A0 | 0.0% | Pending -SHC_3BB0A8C1_0x0049C5C0 | 0.0% | Pending +SHC_3BB0A8C1_0x0049C5C0 | 84.3% | hoisted row ptr and result x -SHC_3BB0A8C1_0x0049C690 | 0.0% | Pending +SHC_3BB0A8C1_0x0049C690 | 77.1% | four gotos as combined conditi SHC_3BB0A8C1_0x0049C730 | 0.0% | Pending -SHC_3BB0A8C1_0x0049CB00 | 0.0% | Pending +SHC_3BB0A8C1_0x0049CB00 | 51.9% | statement order SHC_3BB0A8C1_0x0049CBE0 | 0.0% | Pending -SHC_3BB0A8C1_0x0049CD60 | 0.0% | Pending +SHC_3BB0A8C1_0x0049CD60 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0049CDB0 | 0.0% | Pending -SHC_3BB0A8C1_0x0049CE40 | 0.0% | Pending +SHC_3BB0A8C1_0x0049CE40 | 62.2% | start SHC_3BB0A8C1_0x0049CF30 | 0.0% | Pending -SHC_3BB0A8C1_0x0049D0E0 | 0.0% | Pending +SHC_3BB0A8C1_0x0049D0E0 | 57.1% | signed unit layer local SHC_3BB0A8C1_0x0049D240 | 0.0% | Pending -SHC_3BB0A8C1_0x0049D340 | 0.0% | Pending +SHC_3BB0A8C1_0x0049D340 | 73.2% | start SHC_3BB0A8C1_0x0049D470 | 0.0% | Pending SHC_3BB0A8C1_0x0049D520 | 0.0% | Pending -SHC_3BB0A8C1_0x0049D640 | 0.0% | Pending +SHC_3BB0A8C1_0x0049D640 | 78.5% | start -SHC_3BB0A8C1_0x0049D880 | 0.0% | Pending +SHC_3BB0A8C1_0x0049D880 | 80.7% | Style pass, asm differs SHC_3BB0A8C1_0x0049D970 | 0.0% | Pending -SHC_3BB0A8C1_0x0049DB30 | 0.0% | Pending +SHC_3BB0A8C1_0x0049DB30 | 83.3% | statement order -SHC_3BB0A8C1_0x0049DDC0 | 0.0% | Pending +SHC_3BB0A8C1_0x0049DDC0 | 35.6% | bound literals from asm, frame -SHC_3BB0A8C1_0x0049E0D0 | 0.0% | Pending +SHC_3BB0A8C1_0x0049E0D0 | 87.5% | Style pass, asm differs -SHC_3BB0A8C1_0x0049E510 | 0.0% | Pending +SHC_3BB0A8C1_0x0049E510 | 91.7% | Style pass, asm differs -SHC_3BB0A8C1_0x0049E9E0 | 0.0% | Pending +SHC_3BB0A8C1_0x0049E9E0 | 70.0% | statement order SHC_3BB0A8C1_0x0049EB00 | 0.0% | Pending -SHC_3BB0A8C1_0x0049EDF0 | 0.0% | Pending +SHC_3BB0A8C1_0x0049EDF0 | 78.7% | start SHC_3BB0A8C1_0x0049EED0 | 0.0% | Pending -SHC_3BB0A8C1_0x0049F040 | 0.0% | Pending +SHC_3BB0A8C1_0x0049F040 | 86.5% | Style pass, asm differs -SHC_3BB0A8C1_0x0049F2D0 | 0.0% | Pending +SHC_3BB0A8C1_0x0049F2D0 | 86.0% | Style pass, asm differs -SHC_3BB0A8C1_0x0049F540 | 0.0% | Pending +SHC_3BB0A8C1_0x0049F540 | 86.5% | Style pass, asm differs -SHC_3BB0A8C1_0x0049F7D0 | 0.0% | Pending +SHC_3BB0A8C1_0x0049F7D0 | 32.3% | comma expr expanded, tie SHC_3BB0A8C1_0x0049F9B0 | 0.0% | Pending -SHC_3BB0A8C1_0x0049FC00 | 0.0% | Pending +SHC_3BB0A8C1_0x0049FC00 | 62.5% | redundant parens removed SHC_3BB0A8C1_0x0049FD10 | 0.0% | Pending SHC_3BB0A8C1_0x0049FD70 | 0.0% | Pending -SHC_3BB0A8C1_0x0049FF20 | 0.0% | Pending +SHC_3BB0A8C1_0x0049FF20 | 72.3% | entity id in an int local SHC_3BB0A8C1_0x004A0050 | 0.0% | Pending -SHC_3BB0A8C1_0x004A01D0 | 0.0% | Pending +SHC_3BB0A8C1_0x004A01D0 | 58.2% | start SHC_3BB0A8C1_0x004A0300 | 0.0% | Pending -SHC_3BB0A8C1_0x004A0460 | 0.0% | Pending +SHC_3BB0A8C1_0x004A0460 | 71.4% | statement order -SHC_3BB0A8C1_0x004A06B0 | 0.0% | Pending +SHC_3BB0A8C1_0x004A06B0 | 61.9% | statement order SHC_3BB0A8C1_0x004A07C0 | 0.0% | Pending -SHC_3BB0A8C1_0x004A08E0 | 0.0% | Pending +SHC_3BB0A8C1_0x004A08E0 | 86.2% | statement order -SHC_3BB0A8C1_0x004A0B20 | 0.0% | Pending +SHC_3BB0A8C1_0x004A0B20 | 66.5% | statement order SHC_3BB0A8C1_0x004A0BD0 | 0.0% | Pending @@ -24875,9 +24875,9 @@ SHC_3BB0A8C1_0x004A0E4A | 0.0% | Pending SHC_3BB0A8C1_0x004A0E4B | 0.0% | Pending -SHC_3BB0A8C1_0x004A0E50 | 0.0% | Pending +SHC_3BB0A8C1_0x004A0E50 | 99.2% | start -SHC_3BB0A8C1_0x004A1230 | 0.0% | Pending +SHC_3BB0A8C1_0x004A1230 | 60.8% | statement order SHC_3BB0A8C1_0x004A1568 | 0.0% | Pending @@ -25011,9 +25011,9 @@ SHC_3BB0A8C1_0x004A15AE | 0.0% | Pending SHC_3BB0A8C1_0x004A15AF | 0.0% | Pending -SHC_3BB0A8C1_0x004A15B0 | 0.0% | Pending +SHC_3BB0A8C1_0x004A15B0 | 91.2% | hoisted squared distance -SHC_3BB0A8C1_0x004A16C0 | 0.0% | Pending +SHC_3BB0A8C1_0x004A16C0 | 97.3% | reuse computed start tile SHC_3BB0A8C1_0x004A1800 | 0.0% | Pending @@ -25163,29 +25163,29 @@ SHC_3BB0A8C1_0x004A19AD | 0.0% | Pending SHC_3BB0A8C1_0x004A19AE | 0.0% | Pending -SHC_3BB0A8C1_0x004A19B0 | 0.0% | Pending +SHC_3BB0A8C1_0x004A19B0 | 62.3% | byte linkage local SHC_3BB0A8C1_0x004A1AF0 | 0.0% | Pending -SHC_3BB0A8C1_0x004A1C40 | 0.0% | Pending +SHC_3BB0A8C1_0x004A1C40 | 98.7% | compare operand order SHC_3BB0A8C1_0x004A1CC0 | 0.0% | Pending -SHC_3BB0A8C1_0x004A1D30 | 0.0% | Pending +SHC_3BB0A8C1_0x004A1D30 | 70.5% | walk store via queue field SHC_3BB0A8C1_0x004A1E10 | 0.0% | Pending -SHC_3BB0A8C1_0x004A21B0 | 0.0% | Pending +SHC_3BB0A8C1_0x004A21B0 | 84.8% | statement order SHC_3BB0A8C1_0x004A22C0 | 0.0% | Pending -SHC_3BB0A8C1_0x004A2650 | 0.0% | Pending +SHC_3BB0A8C1_0x004A2650 | 65.7% | building id in an int local SHC_3BB0A8C1_0x004A2740 | 0.0% | Pending SHC_3BB0A8C1_0x004A27D0 | 0.0% | Pending -SHC_3BB0A8C1_0x004A2A90 | 0.0% | Pending +SHC_3BB0A8C1_0x004A2A90 | 65.2% | narrowing cast removed, tie SHC_3BB0A8C1_0x004A2B70 | 0.0% | Pending @@ -25201,27 +25201,27 @@ SHC_3BB0A8C1_0x004A2DC4 | 0.0% | Pending SHC_3BB0A8C1_0x004A2DC8 | 0.0% | Pending -SHC_3BB0A8C1_0x004A2DD0 | 0.0% | Pending +SHC_3BB0A8C1_0x004A2DD0 | 77.8% | signed start row local SHC_3BB0A8C1_0x004A2F00 | 0.0% | Pending SHC_3BB0A8C1_0x004A31D0 | 0.0% | Pending -SHC_3BB0A8C1_0x004A3220 | 0.0% | Pending +SHC_3BB0A8C1_0x004A3220 | 77.2% | signed start row local -SHC_3BB0A8C1_0x004A36B0 | 0.0% | Pending +SHC_3BB0A8C1_0x004A36B0 | 82.7% | signed queue reads SHC_3BB0A8C1_0x004A37D0 | 0.0% | Pending SHC_3BB0A8C1_0x004A3860 | 0.0% | Pending -SHC_3BB0A8C1_0x004A3B20 | 0.0% | Pending +SHC_3BB0A8C1_0x004A3B20 | 47.8% | start SHC_3BB0A8C1_0x004A3E80 | 0.0% | Pending -SHC_3BB0A8C1_0x004A4140 | 0.0% | Pending +SHC_3BB0A8C1_0x004A4140 | 85.5% | redundant parens removed -SHC_3BB0A8C1_0x004A4470 | 0.0% | Pending +SHC_3BB0A8C1_0x004A4470 | 51.1% | start mark from queue field SHC_3BB0A8C1_0x004A4500 | 0.0% | Pending @@ -25229,15 +25229,15 @@ SHC_3BB0A8C1_0x004A4550 | 0.0% | Pending SHC_3BB0A8C1_0x004A46C0 | 0.0% | Pending -SHC_3BB0A8C1_0x004A4930 | 0.0% | Pending +SHC_3BB0A8C1_0x004A4930 | 75.7% | widen locals to int -SHC_3BB0A8C1_0x004A4B30 | 0.0% | Pending +SHC_3BB0A8C1_0x004A4B30 | 79.0% | Style pass, asm differs SHC_3BB0A8C1_0x004A4B80 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x004A4BB0 | 0.0% | Pending +SHC_3BB0A8C1_0x004A4BB0 | 65.3% | statement order -SHC_3BB0A8C1_0x004A4C70 | 0.0% | Pending +SHC_3BB0A8C1_0x004A4C70 | 89.8% | Style pass, asm differs SHC_3BB0A8C1_0x004A4D60 | 0.0% | Pending @@ -25249,61 +25249,61 @@ SHC_3BB0A8C1_0x004A50E0 | 0.0% | Pending SHC_3BB0A8C1_0x004A5230 | 0.0% | Pending -SHC_3BB0A8C1_0x004A52D0 | 0.0% | Pending +SHC_3BB0A8C1_0x004A52D0 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x004A5320 | 0.0% | Pending +SHC_3BB0A8C1_0x004A5320 | 68.8% | redundant parens removed SHC_3BB0A8C1_0x004A5420 | 0.0% | Pending SHC_3BB0A8C1_0x004A5770 | 0.0% | Pending -SHC_3BB0A8C1_0x004A58A0 | 0.0% | Pending +SHC_3BB0A8C1_0x004A58A0 | 37.9% | shared blocks duplicated, inne SHC_3BB0A8C1_0x004A5980 | 0.0% | Pending SHC_3BB0A8C1_0x004A5A30 | 0.0% | Pending -SHC_3BB0A8C1_0x004A5B00 | 0.0% | Pending +SHC_3BB0A8C1_0x004A5B00 | 57.4% | Style pass, asm differs -SHC_3BB0A8C1_0x004A5DA0 | 0.0% | Pending +SHC_3BB0A8C1_0x004A5DA0 | 86.5% | compare operand order SHC_3BB0A8C1_0x004A5F60 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x004A5F90 | 0.0% | Pending +SHC_3BB0A8C1_0x004A5F90 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x004A6010 | 0.0% | Pending +SHC_3BB0A8C1_0x004A6010 | 49.4% | start SHC_3BB0A8C1_0x004A6120 | 0.0% | Pending -SHC_3BB0A8C1_0x004A6520 | 0.0% | Pending +SHC_3BB0A8C1_0x004A6520 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x004A65E0 | 0.0% | Pending +SHC_3BB0A8C1_0x004A65E0 | 73.4% | statement order -SHC_3BB0A8C1_0x004A66D0 | 0.0% | Pending +SHC_3BB0A8C1_0x004A66D0 | 96.9% | compare operand order -SHC_3BB0A8C1_0x004A67D0 | 0.0% | Pending +SHC_3BB0A8C1_0x004A67D0 | 73.1% | compare against 0 not 1 SHC_3BB0A8C1_0x004A6940 | 0.0% | Pending -SHC_3BB0A8C1_0x004A69F0 | 0.0% | Pending +SHC_3BB0A8C1_0x004A69F0 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x004A6AB0 | 0.0% | Pending +SHC_3BB0A8C1_0x004A6AB0 | 65.9% | narrowing cast removed, tie SHC_3BB0A8C1_0x004A6BE0 | 0.0% | Pending SHC_3BB0A8C1_0x004A6C40 | 0.0% | Pending -SHC_3BB0A8C1_0x004A6DF0 | 0.0% | Pending +SHC_3BB0A8C1_0x004A6DF0 | 85.4% | start SHC_3BB0A8C1_0x004A6ED0 | 0.0% | Pending -SHC_3BB0A8C1_0x004A7090 | 0.0% | Pending +SHC_3BB0A8C1_0x004A7090 | 99.6% | named matrix end field -SHC_3BB0A8C1_0x004A75B0 | 0.0% | Pending +SHC_3BB0A8C1_0x004A75B0 | 49.2% | clamp arms from asm -SHC_3BB0A8C1_0x004A79A0 | 0.0% | Pending +SHC_3BB0A8C1_0x004A79A0 | 65.0% | clamp arms reordered -SHC_3BB0A8C1_0x004A7F50 | 0.0% | Pending +SHC_3BB0A8C1_0x004A7F50 | 67.0% | start SHC_3BB0A8C1_0x004A80B0 | 0.0% | Pending @@ -25311,15 +25311,15 @@ SHC_3BB0A8C1_0x004A8220 | 0.0% | Pending SHC_3BB0A8C1_0x004A8340 | 0.0% | Pending -SHC_3BB0A8C1_0x004A83B0 | 0.0% | Pending +SHC_3BB0A8C1_0x004A83B0 | 74.3% | clamp arms reordered -SHC_3BB0A8C1_0x004A8780 | 0.0% | Pending +SHC_3BB0A8C1_0x004A8780 | 81.5% | counted for + named layer -SHC_3BB0A8C1_0x004A8860 | 0.0% | Pending +SHC_3BB0A8C1_0x004A8860 | 49.5% | redundant short casts removed SHC_3BB0A8C1_0x004A8900 | 0.0% | Pending -SHC_3BB0A8C1_0x004A8AB0 | 0.0% | Pending +SHC_3BB0A8C1_0x004A8AB0 | 80.1% | narrowing index casts removed SHC_3BB0A8C1_0x004A91B0 | 0.0% | Pending @@ -25453,23 +25453,23 @@ SHC_3BB0A8C1_0x004A91F6 | 0.0% | Pending SHC_3BB0A8C1_0x004A91F7 | 0.0% | Pending -SHC_3BB0A8C1_0x004A9200 | 0.0% | Pending +SHC_3BB0A8C1_0x004A9200 | 74.2% | start SHC_3BB0A8C1_0x004A94E0 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x004A9510 | 0.0% | Pending +SHC_3BB0A8C1_0x004A9510 | 73.0% | ladder sizes as one condition -SHC_3BB0A8C1_0x004A9680 | 0.0% | Pending +SHC_3BB0A8C1_0x004A9680 | 100.0% | Reimplemented SHC_3BB0A8C1_0x004A96B0 | 0.0% | Pending -SHC_3BB0A8C1_0x004A9760 | 0.0% | Pending +SHC_3BB0A8C1_0x004A9760 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x004A97D0 | 0.0% | Pending +SHC_3BB0A8C1_0x004A97D0 | 31.8% | building id in an int local SHC_3BB0A8C1_0x004A98C0 | 0.0% | Pending -SHC_3BB0A8C1_0x004A9B20 | 0.0% | Pending +SHC_3BB0A8C1_0x004A9B20 | 60.0% | duplicated the shared fallback SHC_3BB0A8C1_0x004A9DD0 | 100.0% | Reimplemented @@ -25477,11 +25477,11 @@ SHC_3BB0A8C1_0x004A9E00 | 0.0% | Pending SHC_3BB0A8C1_0x004A9E60 | 0.0% | Pending -SHC_3BB0A8C1_0x004A9E80 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004A9E80 | 0.0% | Pending SHC_3BB0A8C1_0x004A9E90 | 0.0% | Pending -SHC_3BB0A8C1_0x004A9EB0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004A9EB0 | 0.0% | Pending SHC_3BB0A8C1_0x004A9ED0 | 0.0% | Pending @@ -25519,37 +25519,37 @@ SHC_3BB0A8C1_0x004AA930 | 0.0% | Pending SHC_3BB0A8C1_0x004AA970 | 0.0% | Pending -SHC_3BB0A8C1_0x004AAA40 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004AAA40 | 0.0% | Pending -SHC_3BB0A8C1_0x004AAA60 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004AAA60 | 0.0% | Pending -SHC_3BB0A8C1_0x004AAA80 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004AAA80 | 0.0% | Pending -SHC_3BB0A8C1_0x004AAAA0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004AAAA0 | 0.0% | Pending -SHC_3BB0A8C1_0x004AAAC0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004AAAC0 | 0.0% | Pending -SHC_3BB0A8C1_0x004AAAE0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004AAAE0 | 0.0% | Pending -SHC_3BB0A8C1_0x004AAB00 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004AAB00 | 0.0% | Pending -SHC_3BB0A8C1_0x004AAB20 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004AAB20 | 0.0% | Pending -SHC_3BB0A8C1_0x004AAB40 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004AAB40 | 0.0% | Pending SHC_3BB0A8C1_0x004AAB50 | 0.0% | Pending -SHC_3BB0A8C1_0x004AB440 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004AB440 | 0.0% | Pending SHC_3BB0A8C1_0x004AB460 | 0.0% | Pending -SHC_3BB0A8C1_0x004AB4B0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004AB4B0 | 0.0% | Pending -SHC_3BB0A8C1_0x004AB4E0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004AB4E0 | 0.0% | Pending -SHC_3BB0A8C1_0x004AB510 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004AB510 | 0.0% | Pending -SHC_3BB0A8C1_0x004AB540 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004AB540 | 0.0% | Pending SHC_3BB0A8C1_0x004AB570 | 0.0% | Pending @@ -25619,17 +25619,17 @@ SHC_3BB0A8C1_0x004ABB91 | 0.0% | Pending SHC_3BB0A8C1_0x004ABBA0 | 0.0% | Pending -SHC_3BB0A8C1_0x004ABCB0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004ABCB0 | 0.0% | Pending -SHC_3BB0A8C1_0x004ABCE0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004ABCE0 | 0.0% | Pending -SHC_3BB0A8C1_0x004ABD10 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004ABD10 | 0.0% | Pending SHC_3BB0A8C1_0x004ABD20 | 0.0% | Pending -SHC_3BB0A8C1_0x004ABE50 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004ABE50 | 0.0% | Pending -SHC_3BB0A8C1_0x004ABE80 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004ABE80 | 0.0% | Pending SHC_3BB0A8C1_0x004ABEB0 | 0.0% | Pending @@ -25779,7 +25779,7 @@ SHC_3BB0A8C1_0x004AC24E | 0.0% | Pending SHC_3BB0A8C1_0x004AC24F | 0.0% | Pending -SHC_3BB0A8C1_0x004AC250 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004AC250 | 0.0% | Pending SHC_3BB0A8C1_0x004AC280 | 0.0% | Pending @@ -25903,31 +25903,31 @@ SHC_3BB0A8C1_0x004AF4C0 | 0.0% | Pending SHC_3BB0A8C1_0x004AF5E0 | 0.0% | Pending -SHC_3BB0A8C1_0x004AF630 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004AF630 | 0.0% | Pending -SHC_3BB0A8C1_0x004AF650 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004AF650 | 0.0% | Pending -SHC_3BB0A8C1_0x004AF680 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004AF680 | 0.0% | Pending -SHC_3BB0A8C1_0x004AF6B0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004AF6B0 | 0.0% | Pending -SHC_3BB0A8C1_0x004AF6E0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004AF6E0 | 0.0% | Pending SHC_3BB0A8C1_0x004AF700 | 0.0% | Pending -SHC_3BB0A8C1_0x004AF800 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004AF800 | 0.0% | Pending -SHC_3BB0A8C1_0x004AF820 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004AF820 | 0.0% | Pending -SHC_3BB0A8C1_0x004AF840 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004AF840 | 0.0% | Pending SHC_3BB0A8C1_0x004AF860 | 0.0% | Pending -SHC_3BB0A8C1_0x004AFA50 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004AFA50 | 0.0% | Pending SHC_3BB0A8C1_0x004AFA80 | 0.0% | Pending -SHC_3BB0A8C1_0x004AFB00 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004AFB00 | 0.0% | Pending SHC_3BB0A8C1_0x004AFB30 | 0.0% | Pending @@ -25967,7 +25967,7 @@ SHC_3BB0A8C1_0x004B0F70 | 0.0% | Pending SHC_3BB0A8C1_0x004B1000 | 0.0% | Pending -SHC_3BB0A8C1_0x004B1090 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004B1090 | 0.0% | Pending SHC_3BB0A8C1_0x004B10D0 | 0.0% | Pending @@ -26001,7 +26001,7 @@ SHC_3BB0A8C1_0x004B1E60 | 0.0% | Pending SHC_3BB0A8C1_0x004B1EB0 | 0.0% | Pending -SHC_3BB0A8C1_0x004B20B0 | 82.4% | shared arm fold direction +SHC_3BB0A8C1_0x004B20B0 | 0.0% | Pending SHC_3BB0A8C1_0x004B2280 | 0.0% | Pending @@ -26881,7 +26881,7 @@ SHC_3BB0A8C1_0x004B51A0 | 0.0% | Pending SHC_3BB0A8C1_0x004B5280 | 0.0% | Pending -SHC_3BB0A8C1_0x004B5300 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004B5300 | 0.0% | Pending SHC_3BB0A8C1_0x004B5330 | 0.0% | Pending @@ -26905,7 +26905,7 @@ SHC_3BB0A8C1_0x004B6480 | 0.0% | Pending SHC_3BB0A8C1_0x004B64D0 | 0.0% | Pending -SHC_3BB0A8C1_0x004B6500 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004B6500 | 0.0% | Pending SHC_3BB0A8C1_0x004B6530 | 0.0% | Pending @@ -26915,9 +26915,9 @@ SHC_3BB0A8C1_0x004B65A0 | 0.0% | Pending SHC_3BB0A8C1_0x004B65F0 | 0.0% | Pending -SHC_3BB0A8C1_0x004B6640 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004B6640 | 0.0% | Pending -SHC_3BB0A8C1_0x004B6680 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004B6680 | 0.0% | Pending SHC_3BB0A8C1_0x004B66C0 | 0.0% | Pending @@ -27071,17 +27071,17 @@ SHC_3BB0A8C1_0x004B7530 | 0.0% | Pending SHC_3BB0A8C1_0x004B7600 | 0.0% | Pending -SHC_3BB0A8C1_0x004B7700 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004B7700 | 0.0% | Pending SHC_3BB0A8C1_0x004B7730 | 0.0% | Pending SHC_3BB0A8C1_0x004B77A0 | 0.0% | Pending -SHC_3BB0A8C1_0x004B77E0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004B77E0 | 0.0% | Pending SHC_3BB0A8C1_0x004B7800 | 0.0% | Pending -SHC_3BB0A8C1_0x004B7890 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004B7890 | 0.0% | Pending SHC_3BB0A8C1_0x004B78D0 | 0.0% | Pending @@ -27097,19 +27097,19 @@ SHC_3BB0A8C1_0x004B7AF0 | 0.0% | Pending SHC_3BB0A8C1_0x004B7C90 | 0.0% | Pending -SHC_3BB0A8C1_0x004B7F60 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004B7F60 | 0.0% | Pending SHC_3BB0A8C1_0x004B7FA0 | 0.0% | Pending SHC_3BB0A8C1_0x004B8000 | 0.0% | Pending -SHC_3BB0A8C1_0x004B8050 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004B8050 | 0.0% | Pending SHC_3BB0A8C1_0x004B8080 | 0.0% | Pending -SHC_3BB0A8C1_0x004B8200 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004B8200 | 0.0% | Pending -SHC_3BB0A8C1_0x004B8210 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004B8210 | 0.0% | Pending SHC_3BB0A8C1_0x004B8220 | 0.0% | Pending @@ -27639,7 +27639,7 @@ SHC_3BB0A8C1_0x004B9528 | 0.0% | Pending SHC_3BB0A8C1_0x004B9530 | 0.0% | Pending -SHC_3BB0A8C1_0x004B9610 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004B9610 | 0.0% | Pending SHC_3BB0A8C1_0x004B9620 | 0.0% | Pending @@ -29119,7 +29119,7 @@ SHC_3BB0A8C1_0x004BAEC0 | 0.0% | Pending SHC_3BB0A8C1_0x004BB010 | 0.0% | Pending -SHC_3BB0A8C1_0x004BB0B0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004BB0B0 | 0.0% | Pending SHC_3BB0A8C1_0x004BB0D0 | 0.0% | Pending @@ -29287,11 +29287,11 @@ SHC_3BB0A8C1_0x004BB52C | 0.0% | Pending SHC_3BB0A8C1_0x004BB530 | 0.0% | Pending -SHC_3BB0A8C1_0x004BB540 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004BB540 | 0.0% | Pending SHC_3BB0A8C1_0x004BB570 | 0.0% | Pending -SHC_3BB0A8C1_0x004BB650 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004BB650 | 0.0% | Pending SHC_3BB0A8C1_0x004BB680 | 0.0% | Pending @@ -29315,9 +29315,9 @@ SHC_3BB0A8C1_0x004BB900 | 0.0% | Pending SHC_3BB0A8C1_0x004BB990 | 0.0% | Pending -SHC_3BB0A8C1_0x004BB9F0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004BB9F0 | 0.0% | Pending -SHC_3BB0A8C1_0x004BBA20 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004BBA20 | 0.0% | Pending SHC_3BB0A8C1_0x004BBA30 | 0.0% | Pending @@ -30085,17 +30085,17 @@ SHC_3BB0A8C1_0x004BC5B0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x004BC5F0 | 0.0% | Pending -SHC_3BB0A8C1_0x004BC620 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004BC620 | 0.0% | Pending SHC_3BB0A8C1_0x004BC630 | 0.0% | Pending -SHC_3BB0A8C1_0x004BC690 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004BC690 | 0.0% | Pending SHC_3BB0A8C1_0x004BC6C0 | 0.0% | Pending SHC_3BB0A8C1_0x004BC6F0 | 0.0% | Pending -SHC_3BB0A8C1_0x004BC770 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004BC770 | 0.0% | Pending SHC_3BB0A8C1_0x004BC790 | 0.0% | Pending @@ -30491,7 +30491,7 @@ SHC_3BB0A8C1_0x004BEA90 | 0.0% | Pending SHC_3BB0A8C1_0x004BEB20 | 0.0% | Pending -SHC_3BB0A8C1_0x004BEC10 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004BEC10 | 0.0% | Pending SHC_3BB0A8C1_0x004BEC40 | 0.0% | Pending @@ -35833,7 +35833,7 @@ SHC_3BB0A8C1_0x004D6D14 | 0.0% | Pending SHC_3BB0A8C1_0x004D6D20 | 0.0% | Pending -SHC_3BB0A8C1_0x004D6EF0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004D6EF0 | 0.0% | Pending SHC_3BB0A8C1_0x004D6F20 | 0.0% | Pending @@ -35999,7 +35999,7 @@ SHC_3BB0A8C1_0x004D8A18 | 0.0% | Pending SHC_3BB0A8C1_0x004D8A20 | 0.0% | Pending -SHC_3BB0A8C1_0x004D8AB0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004D8AB0 | 0.0% | Pending SHC_3BB0A8C1_0x004D8AE0 | 0.0% | Pending @@ -36019,7 +36019,7 @@ SHC_3BB0A8C1_0x004D91D0 | 0.0% | Pending SHC_3BB0A8C1_0x004D9230 | 0.0% | Pending -SHC_3BB0A8C1_0x004D9270 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004D9270 | 0.0% | Pending SHC_3BB0A8C1_0x004D9290 | 0.0% | Pending @@ -36027,7 +36027,7 @@ SHC_3BB0A8C1_0x004D9400 | 0.0% | Pending SHC_3BB0A8C1_0x004D9520 | 0.0% | Pending -SHC_3BB0A8C1_0x004D9700 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004D9700 | 0.0% | Pending SHC_3BB0A8C1_0x004D9730 | 0.0% | Pending @@ -36053,9 +36053,9 @@ SHC_3BB0A8C1_0x004D9C10 | 0.0% | Pending SHC_3BB0A8C1_0x004D9CC0 | 0.0% | Pending -SHC_3BB0A8C1_0x004D9D60 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004D9D60 | 0.0% | Pending -SHC_3BB0A8C1_0x004D9D90 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004D9D90 | 0.0% | Pending SHC_3BB0A8C1_0x004D9DB0 | 0.0% | Pending @@ -36135,7 +36135,7 @@ SHC_3BB0A8C1_0x004DA360 | 0.0% | Pending SHC_3BB0A8C1_0x004DA570 | 0.0% | Pending -SHC_3BB0A8C1_0x004DA640 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004DA640 | 0.0% | Pending SHC_3BB0A8C1_0x004DA670 | 0.0% | Pending @@ -36145,15 +36145,15 @@ SHC_3BB0A8C1_0x004DA750 | 0.0% | Pending SHC_3BB0A8C1_0x004DA7A0 | 0.0% | Pending -SHC_3BB0A8C1_0x004DA7E0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004DA7E0 | 0.0% | Pending -SHC_3BB0A8C1_0x004DA810 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004DA810 | 0.0% | Pending -SHC_3BB0A8C1_0x004DA840 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004DA840 | 0.0% | Pending -SHC_3BB0A8C1_0x004DA870 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004DA870 | 0.0% | Pending -SHC_3BB0A8C1_0x004DA8A0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004DA8A0 | 0.0% | Pending SHC_3BB0A8C1_0x004DA8D0 | 0.0% | Pending @@ -36171,7 +36171,7 @@ SHC_3BB0A8C1_0x004DAB80 | 0.0% | Pending SHC_3BB0A8C1_0x004DABB0 | 0.0% | Pending -SHC_3BB0A8C1_0x004DABF0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004DABF0 | 0.0% | Pending SHC_3BB0A8C1_0x004DAC30 | 0.0% | Pending @@ -36257,7 +36257,7 @@ SHC_3BB0A8C1_0x004DC500 | 0.0% | Pending SHC_3BB0A8C1_0x004DC9E0 | 0.0% | Pending -SHC_3BB0A8C1_0x004DCC70 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004DCC70 | 0.0% | Pending SHC_3BB0A8C1_0x004DCC90 | 0.0% | Pending @@ -36375,7 +36375,7 @@ SHC_3BB0A8C1_0x004E12C0 | 0.0% | Pending SHC_3BB0A8C1_0x004E1810 | 0.0% | Pending -SHC_3BB0A8C1_0x004E1A20 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004E1A20 | 0.0% | Pending SHC_3BB0A8C1_0x004E1A50 | 0.0% | Pending @@ -36399,7 +36399,7 @@ SHC_3BB0A8C1_0x004E2460 | 0.0% | Pending SHC_3BB0A8C1_0x004E25A0 | 0.0% | Pending -SHC_3BB0A8C1_0x004E2600 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004E2600 | 0.0% | Pending SHC_3BB0A8C1_0x004E2630 | 0.0% | Pending @@ -36985,7 +36985,7 @@ SHC_3BB0A8C1_0x004E66F0 | 0.0% | Pending SHC_3BB0A8C1_0x004E7770 | 0.0% | Pending -SHC_3BB0A8C1_0x004E7800 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004E7800 | 0.0% | Pending SHC_3BB0A8C1_0x004E7810 | 0.0% | Pending @@ -37335,11 +37335,11 @@ SHC_3BB0A8C1_0x004E8C4C | 0.0% | Pending SHC_3BB0A8C1_0x004E8C50 | 0.0% | Pending -SHC_3BB0A8C1_0x004E8C90 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004E8C90 | 0.0% | Pending -SHC_3BB0A8C1_0x004E8CA0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004E8CA0 | 0.0% | Pending -SHC_3BB0A8C1_0x004E8CC0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004E8CC0 | 0.0% | Pending SHC_3BB0A8C1_0x004E8CF0 | 0.0% | Pending @@ -38463,7 +38463,7 @@ SHC_3BB0A8C1_0x004F28E4 | 0.0% | Pending SHC_3BB0A8C1_0x004F28E8 | 0.0% | Pending -SHC_3BB0A8C1_0x004F28F0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004F28F0 | 0.0% | Pending SHC_3BB0A8C1_0x004F2920 | 0.0% | Pending @@ -38561,9 +38561,9 @@ SHC_3BB0A8C1_0x004F2E00 | 0.0% | Pending SHC_3BB0A8C1_0x004F2E90 | 0.0% | Pending -SHC_3BB0A8C1_0x004F2FB0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004F2FB0 | 0.0% | Pending -SHC_3BB0A8C1_0x004F2FE0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004F2FE0 | 0.0% | Pending SHC_3BB0A8C1_0x004F3010 | 0.0% | Pending @@ -38579,7 +38579,7 @@ SHC_3BB0A8C1_0x004F3560 | 0.0% | Pending SHC_3BB0A8C1_0x004F3610 | 0.0% | Pending -SHC_3BB0A8C1_0x004F3700 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004F3700 | 0.0% | Pending SHC_3BB0A8C1_0x004F3730 | 0.0% | Pending @@ -38589,9 +38589,9 @@ SHC_3BB0A8C1_0x004F3840 | 0.0% | Pending SHC_3BB0A8C1_0x004F38A0 | 0.0% | Pending -SHC_3BB0A8C1_0x004F3900 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004F3900 | 0.0% | Pending -SHC_3BB0A8C1_0x004F3930 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004F3930 | 0.0% | Pending SHC_3BB0A8C1_0x004F3960 | 0.0% | Pending @@ -38599,7 +38599,7 @@ SHC_3BB0A8C1_0x004F3B90 | 0.0% | Pending SHC_3BB0A8C1_0x004F3C50 | 0.0% | Pending -SHC_3BB0A8C1_0x004F3D30 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004F3D30 | 0.0% | Pending SHC_3BB0A8C1_0x004F3D60 | 0.0% | Pending @@ -38633,9 +38633,9 @@ SHC_3BB0A8C1_0x004F4290 | 0.0% | Pending SHC_3BB0A8C1_0x004F49D0 | 0.0% | Pending -SHC_3BB0A8C1_0x004F4C30 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004F4C30 | 0.0% | Pending -SHC_3BB0A8C1_0x004F4C60 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004F4C60 | 0.0% | Pending SHC_3BB0A8C1_0x004F4C80 | 0.0% | Pending @@ -38697,7 +38697,7 @@ SHC_3BB0A8C1_0x004F6460 | 0.0% | Pending SHC_3BB0A8C1_0x004F6464 | 0.0% | Pending -SHC_3BB0A8C1_0x004F6470 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004F6470 | 0.0% | Pending SHC_3BB0A8C1_0x004F64A0 | 0.0% | Pending @@ -38733,9 +38733,9 @@ SHC_3BB0A8C1_0x004F69D0 | 0.0% | Pending SHC_3BB0A8C1_0x004F6A20 | 0.0% | Pending -SHC_3BB0A8C1_0x004F6A60 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004F6A60 | 0.0% | Pending -SHC_3BB0A8C1_0x004F6A70 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004F6A70 | 0.0% | Pending SHC_3BB0A8C1_0x004F6A80 | 0.0% | Pending @@ -38755,11 +38755,11 @@ SHC_3BB0A8C1_0x004F6F90 | 0.0% | Pending SHC_3BB0A8C1_0x004F6FD0 | 0.0% | Pending -SHC_3BB0A8C1_0x004F70B0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004F70B0 | 0.0% | Pending SHC_3BB0A8C1_0x004F70D0 | 0.0% | Pending -SHC_3BB0A8C1_0x004F70E0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x004F70E0 | 0.0% | Pending SHC_3BB0A8C1_0x004F70F0 | 0.0% | Pending @@ -41419,19 +41419,19 @@ SHC_3BB0A8C1_0x00500090 | 0.0% | Pending SHC_3BB0A8C1_0x00500091 | 0.0% | Pending -SHC_3BB0A8C1_0x005000A0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x005000A0 | 0.0% | Pending SHC_3BB0A8C1_0x005000E0 | 0.0% | Pending SHC_3BB0A8C1_0x00500180 | 0.0% | Pending -SHC_3BB0A8C1_0x00500210 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00500210 | 0.0% | Pending SHC_3BB0A8C1_0x00500250 | 0.0% | Pending SHC_3BB0A8C1_0x00500290 | 0.0% | Pending -SHC_3BB0A8C1_0x005002D0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x005002D0 | 0.0% | Pending SHC_3BB0A8C1_0x00500310 | 0.0% | Pending @@ -41443,19 +41443,19 @@ SHC_3BB0A8C1_0x00500500 | 0.0% | Pending SHC_3BB0A8C1_0x005005F0 | 0.0% | Pending -SHC_3BB0A8C1_0x00500640 | 46.2% | register allocation differs +SHC_3BB0A8C1_0x00500640 | 0.0% | Pending -SHC_3BB0A8C1_0x00500680 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00500680 | 0.0% | Pending SHC_3BB0A8C1_0x005006C0 | 0.0% | Pending -SHC_3BB0A8C1_0x00500720 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00500720 | 0.0% | Pending -SHC_3BB0A8C1_0x00500750 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00500750 | 0.0% | Pending SHC_3BB0A8C1_0x00500790 | 0.0% | Pending -SHC_3BB0A8C1_0x005007D0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x005007D0 | 0.0% | Pending SHC_3BB0A8C1_0x00500800 | 0.0% | Pending @@ -41471,25 +41471,25 @@ SHC_3BB0A8C1_0x00500B50 | 0.0% | Pending SHC_3BB0A8C1_0x00500BB0 | 0.0% | Pending -SHC_3BB0A8C1_0x00500C20 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00500C20 | 0.0% | Pending -SHC_3BB0A8C1_0x00500C80 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00500C80 | 0.0% | Pending -SHC_3BB0A8C1_0x00500CB0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00500CB0 | 0.0% | Pending -SHC_3BB0A8C1_0x00500CF0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00500CF0 | 0.0% | Pending -SHC_3BB0A8C1_0x00500D30 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00500D30 | 0.0% | Pending -SHC_3BB0A8C1_0x00500D60 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00500D60 | 0.0% | Pending -SHC_3BB0A8C1_0x00500DD0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00500DD0 | 0.0% | Pending -SHC_3BB0A8C1_0x00500E20 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00500E20 | 0.0% | Pending -SHC_3BB0A8C1_0x00500EE0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00500EE0 | 0.0% | Pending -SHC_3BB0A8C1_0x00500F40 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00500F40 | 0.0% | Pending SHC_3BB0A8C1_0x00501070 | 0.0% | Pending @@ -41503,19 +41503,19 @@ SHC_3BB0A8C1_0x005010B8 | 0.0% | Pending SHC_3BB0A8C1_0x005010BC | 0.0% | Pending -SHC_3BB0A8C1_0x005010C0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x005010C0 | 0.0% | Pending SHC_3BB0A8C1_0x005010D0 | 0.0% | Pending -SHC_3BB0A8C1_0x005010E0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x005010E0 | 0.0% | Pending SHC_3BB0A8C1_0x00501110 | 0.0% | Pending -SHC_3BB0A8C1_0x00501180 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00501180 | 0.0% | Pending -SHC_3BB0A8C1_0x005011A0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x005011A0 | 0.0% | Pending -SHC_3BB0A8C1_0x005011C0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x005011C0 | 0.0% | Pending SHC_3BB0A8C1_0x005011F0 | 0.0% | Pending @@ -41535,11 +41535,11 @@ SHC_3BB0A8C1_0x005016D0 | 0.0% | Pending SHC_3BB0A8C1_0x005016E0 | 0.0% | Pending -SHC_3BB0A8C1_0x00501730 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00501730 | 0.0% | Pending SHC_3BB0A8C1_0x00501760 | 0.0% | Pending -SHC_3BB0A8C1_0x005017A0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x005017A0 | 0.0% | Pending SHC_3BB0A8C1_0x005017C0 | 0.0% | Pending @@ -42067,7 +42067,7 @@ SHC_3BB0A8C1_0x00504ED0 | 0.0% | Pending SHC_3BB0A8C1_0x00504ED1 | 0.0% | Pending -SHC_3BB0A8C1_0x00504EE0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00504EE0 | 0.0% | Pending SHC_3BB0A8C1_0x00504F10 | 0.0% | Pending @@ -44191,7 +44191,7 @@ SHC_3BB0A8C1_0x005116E0 | 0.0% | Pending SHC_3BB0A8C1_0x00511850 | 0.0% | Pending -SHC_3BB0A8C1_0x005118C0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x005118C0 | 0.0% | Pending SHC_3BB0A8C1_0x005119A4 | 0.0% | Pending @@ -44739,7 +44739,7 @@ SHC_3BB0A8C1_0x005127B0 | 0.0% | Pending SHC_3BB0A8C1_0x005127D0 | 0.0% | Pending -SHC_3BB0A8C1_0x00512920 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00512920 | 0.0% | Pending SHC_3BB0A8C1_0x00512940 | 0.0% | Pending @@ -45743,7 +45743,7 @@ SHC_3BB0A8C1_0x00518180 | 0.0% | Pending SHC_3BB0A8C1_0x005182A0 | 0.0% | Pending -SHC_3BB0A8C1_0x00518350 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00518350 | 0.0% | Pending SHC_3BB0A8C1_0x00518380 | 0.0% | Pending @@ -45773,7 +45773,7 @@ SHC_3BB0A8C1_0x00519850 | 0.0% | Pending SHC_3BB0A8C1_0x005198C0 | 0.0% | Pending -SHC_3BB0A8C1_0x00519960 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00519960 | 0.0% | Pending SHC_3BB0A8C1_0x00519990 | 0.0% | Pending @@ -45839,9 +45839,9 @@ SHC_3BB0A8C1_0x0051AB60 | 0.0% | Pending SHC_3BB0A8C1_0x0051ABB0 | 0.0% | Pending -SHC_3BB0A8C1_0x0051AC80 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x0051AC80 | 0.0% | Pending -SHC_3BB0A8C1_0x0051ACB0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x0051ACB0 | 0.0% | Pending SHC_3BB0A8C1_0x0051ACE0 | 0.0% | Pending @@ -45879,7 +45879,7 @@ SHC_3BB0A8C1_0x0051B420 | 0.0% | Pending SHC_3BB0A8C1_0x0051B570 | 0.0% | Pending -SHC_3BB0A8C1_0x0051B680 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x0051B680 | 0.0% | Pending SHC_3BB0A8C1_0x0051B690 | 0.0% | Pending @@ -46161,7 +46161,7 @@ SHC_3BB0A8C1_0x0051D5D0 | 0.0% | Pending SHC_3BB0A8C1_0x0051D5E0 | 0.0% | Pending -SHC_3BB0A8C1_0x0051D680 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x0051D680 | 0.0% | Pending SHC_3BB0A8C1_0x0051D690 | 0.0% | Pending @@ -46379,11 +46379,11 @@ SHC_3BB0A8C1_0x00520CD0 | 0.0% | Pending SHC_3BB0A8C1_0x00520F70 | 0.0% | Pending -SHC_3BB0A8C1_0x00521180 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00521180 | 0.0% | Pending SHC_3BB0A8C1_0x005211B0 | 0.0% | Pending -SHC_3BB0A8C1_0x00521210 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00521210 | 0.0% | Pending SHC_3BB0A8C1_0x00521240 | 0.0% | Pending @@ -46633,7 +46633,7 @@ SHC_3BB0A8C1_0x00521EA5 | 0.0% | Pending SHC_3BB0A8C1_0x00521EA6 | 0.0% | Pending -SHC_3BB0A8C1_0x00521EB0 | 76.5% | pop esi scheduling +SHC_3BB0A8C1_0x00521EB0 | 0.0% | Pending SHC_3BB0A8C1_0x00521EF0 | 0.0% | Pending @@ -46765,11 +46765,11 @@ SHC_3BB0A8C1_0x00522083 | 0.0% | Pending SHC_3BB0A8C1_0x00522090 | 0.0% | Pending -SHC_3BB0A8C1_0x00522110 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00522110 | 0.0% | Pending -SHC_3BB0A8C1_0x00522150 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00522150 | 0.0% | Pending -SHC_3BB0A8C1_0x00522160 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00522160 | 0.0% | Pending SHC_3BB0A8C1_0x005221A0 | 0.0% | Pending @@ -46779,15 +46779,15 @@ SHC_3BB0A8C1_0x00522210 | 0.0% | Pending SHC_3BB0A8C1_0x005222B0 | 0.0% | Pending -SHC_3BB0A8C1_0x00522360 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00522360 | 0.0% | Pending SHC_3BB0A8C1_0x00522390 | 0.0% | Pending SHC_3BB0A8C1_0x00522410 | 0.0% | Pending -SHC_3BB0A8C1_0x005224E0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x005224E0 | 0.0% | Pending -SHC_3BB0A8C1_0x00522520 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00522520 | 0.0% | Pending SHC_3BB0A8C1_0x00522550 | 0.0% | Pending @@ -46807,11 +46807,11 @@ SHC_3BB0A8C1_0x005229C0 | 0.0% | Pending SHC_3BB0A8C1_0x00522B00 | 0.0% | Pending -SHC_3BB0A8C1_0x00522BC0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00522BC0 | 0.0% | Pending -SHC_3BB0A8C1_0x00522BF0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00522BF0 | 0.0% | Pending -SHC_3BB0A8C1_0x00522C20 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00522C20 | 0.0% | Pending SHC_3BB0A8C1_0x00522C50 | 0.0% | Pending @@ -46833,13 +46833,13 @@ SHC_3BB0A8C1_0x005232E0 | 0.0% | Pending SHC_3BB0A8C1_0x005232F0 | 0.0% | Pending -SHC_3BB0A8C1_0x00523340 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00523340 | 0.0% | Pending -SHC_3BB0A8C1_0x00523370 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00523370 | 0.0% | Pending SHC_3BB0A8C1_0x005233A0 | 0.0% | Pending -SHC_3BB0A8C1_0x005233E0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x005233E0 | 0.0% | Pending SHC_3BB0A8C1_0x00523410 | 0.0% | Pending @@ -46851,7 +46851,7 @@ SHC_3BB0A8C1_0x00523630 | 0.0% | Pending SHC_3BB0A8C1_0x005236A0 | 0.0% | Pending -SHC_3BB0A8C1_0x00523730 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00523730 | 0.0% | Pending SHC_3BB0A8C1_0x00523750 | 0.0% | Pending @@ -46865,11 +46865,11 @@ SHC_3BB0A8C1_0x00523A30 | 0.0% | Pending SHC_3BB0A8C1_0x00523B00 | 0.0% | Pending -SHC_3BB0A8C1_0x00523E00 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00523E00 | 0.0% | Pending SHC_3BB0A8C1_0x00523E30 | 0.0% | Pending -SHC_3BB0A8C1_0x00523EB0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00523EB0 | 0.0% | Pending SHC_3BB0A8C1_0x00523EF0 | 0.0% | Pending @@ -46917,7 +46917,7 @@ SHC_3BB0A8C1_0x00524EF0 | 0.0% | Pending SHC_3BB0A8C1_0x00525060 | 0.0% | Pending -SHC_3BB0A8C1_0x00525090 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00525090 | 0.0% | Pending SHC_3BB0A8C1_0x005250B0 | 0.0% | Pending @@ -46947,7 +46947,7 @@ SHC_3BB0A8C1_0x00525970 | 0.0% | Pending SHC_3BB0A8C1_0x00525A70 | 0.0% | Pending -SHC_3BB0A8C1_0x00525B70 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00525B70 | 0.0% | Pending SHC_3BB0A8C1_0x00525BA0 | 0.0% | Pending @@ -46959,7 +46959,7 @@ SHC_3BB0A8C1_0x005261B0 | 0.0% | Pending SHC_3BB0A8C1_0x005262A0 | 0.0% | Pending -SHC_3BB0A8C1_0x00526370 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00526370 | 0.0% | Pending SHC_3BB0A8C1_0x005263A0 | 0.0% | Pending @@ -49233,7 +49233,7 @@ SHC_3BB0A8C1_0x0052B9E4 | 0.0% | Pending SHC_3BB0A8C1_0x0052B9E8 | 0.0% | Pending -SHC_3BB0A8C1_0x0052B9F0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x0052B9F0 | 0.0% | Pending SHC_3BB0A8C1_0x0052BA10 | 0.0% | Pending @@ -49317,9 +49317,9 @@ SHC_3BB0A8C1_0x0052EED0 | 0.0% | Pending SHC_3BB0A8C1_0x0052F010 | 0.0% | Pending -SHC_3BB0A8C1_0x0052F070 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x0052F070 | 0.0% | Pending -SHC_3BB0A8C1_0x0052F0A0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x0052F0A0 | 0.0% | Pending SHC_3BB0A8C1_0x0052F0D0 | 0.0% | Pending @@ -49345,9 +49345,9 @@ SHC_3BB0A8C1_0x0052F730 | 0.0% | Pending SHC_3BB0A8C1_0x0052F7E0 | 0.0% | Pending -SHC_3BB0A8C1_0x0052FBB0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x0052FBB0 | 0.0% | Pending -SHC_3BB0A8C1_0x0052FBF0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x0052FBF0 | 0.0% | Pending SHC_3BB0A8C1_0x0052FC30 | 0.0% | Pending @@ -49361,7 +49361,7 @@ SHC_3BB0A8C1_0x0052FE90 | 0.0% | Pending SHC_3BB0A8C1_0x0052FF80 | 0.0% | Pending -SHC_3BB0A8C1_0x00530080 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00530080 | 0.0% | Pending SHC_3BB0A8C1_0x005300B0 | 0.0% | Pending @@ -49649,7 +49649,7 @@ SHC_3BB0A8C1_0x00530C40 | 0.0% | Pending SHC_3BB0A8C1_0x00530CF0 | 0.0% | Pending -SHC_3BB0A8C1_0x00530D50 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00530D50 | 0.0% | Pending SHC_3BB0A8C1_0x00530D70 | 0.0% | Pending @@ -49659,11 +49659,11 @@ SHC_3BB0A8C1_0x00530EB0 | 0.0% | Pending SHC_3BB0A8C1_0x00530F20 | 0.0% | Pending -SHC_3BB0A8C1_0x00530FD0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00530FD0 | 0.0% | Pending SHC_3BB0A8C1_0x00531000 | 0.0% | Pending -SHC_3BB0A8C1_0x005311F0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x005311F0 | 0.0% | Pending SHC_3BB0A8C1_0x00531220 | 0.0% | Pending @@ -50643,7 +50643,7 @@ SHC_3BB0A8C1_0x00532F5D | 0.0% | Pending SHC_3BB0A8C1_0x00532F5E | 0.0% | Pending -SHC_3BB0A8C1_0x00532F60 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00532F60 | 0.0% | Pending SHC_3BB0A8C1_0x00532F80 | 0.0% | Pending @@ -50677,19 +50677,19 @@ SHC_3BB0A8C1_0x00533630 | 0.0% | Pending SHC_3BB0A8C1_0x00533810 | 0.0% | Pending -SHC_3BB0A8C1_0x00533920 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00533920 | 0.0% | Pending SHC_3BB0A8C1_0x00533960 | 0.0% | Pending SHC_3BB0A8C1_0x005339A0 | 0.0% | Pending -SHC_3BB0A8C1_0x005339F0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x005339F0 | 0.0% | Pending SHC_3BB0A8C1_0x00533A10 | 0.0% | Pending SHC_3BB0A8C1_0x00533B30 | 0.0% | Pending -SHC_3BB0A8C1_0x00533C70 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00533C70 | 0.0% | Pending SHC_3BB0A8C1_0x00533CA0 | 0.0% | Pending @@ -50777,7 +50777,7 @@ SHC_3BB0A8C1_0x00533F84 | 0.0% | Pending SHC_3BB0A8C1_0x00533F85 | 0.0% | Pending -SHC_3BB0A8C1_0x00533F90 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00533F90 | 0.0% | Pending SHC_3BB0A8C1_0x00533FC0 | 0.0% | Pending @@ -50809,7 +50809,7 @@ SHC_3BB0A8C1_0x005343C0 | 0.0% | Pending SHC_3BB0A8C1_0x005343F0 | 0.0% | Pending -SHC_3BB0A8C1_0x00534460 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00534460 | 0.0% | Pending SHC_3BB0A8C1_0x00534490 | 0.0% | Pending @@ -50857,7 +50857,7 @@ SHC_3BB0A8C1_0x005350B0 | 0.0% | Pending SHC_3BB0A8C1_0x00535150 | 0.0% | Pending -SHC_3BB0A8C1_0x00535190 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00535190 | 0.0% | Pending SHC_3BB0A8C1_0x005351C0 | 0.0% | Pending @@ -51065,11 +51065,11 @@ SHC_3BB0A8C1_0x00535513 | 0.0% | Pending SHC_3BB0A8C1_0x00535514 | 0.0% | Pending -SHC_3BB0A8C1_0x00535520 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00535520 | 0.0% | Pending -SHC_3BB0A8C1_0x00535550 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00535550 | 0.0% | Pending -SHC_3BB0A8C1_0x00535560 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00535560 | 0.0% | Pending SHC_3BB0A8C1_0x00535580 | 0.0% | Pending @@ -51077,15 +51077,15 @@ SHC_3BB0A8C1_0x005355E0 | 0.0% | Pending SHC_3BB0A8C1_0x00535680 | 0.0% | Pending -SHC_3BB0A8C1_0x00535700 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00535700 | 0.0% | Pending SHC_3BB0A8C1_0x00535730 | 0.0% | Pending SHC_3BB0A8C1_0x005357E0 | 0.0% | Pending -SHC_3BB0A8C1_0x00535810 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00535810 | 0.0% | Pending -SHC_3BB0A8C1_0x00535840 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00535840 | 0.0% | Pending SHC_3BB0A8C1_0x00535870 | 0.0% | Pending @@ -51103,7 +51103,7 @@ SHC_3BB0A8C1_0x00535B00 | 0.0% | Pending SHC_3BB0A8C1_0x00535BC0 | 0.0% | Pending -SHC_3BB0A8C1_0x00535DF0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00535DF0 | 0.0% | Pending SHC_3BB0A8C1_0x00535E20 | 0.0% | Pending @@ -51205,9 +51205,9 @@ SHC_3BB0A8C1_0x00536A60 | 0.0% | Pending SHC_3BB0A8C1_0x00536C70 | 0.0% | Pending -SHC_3BB0A8C1_0x00536C90 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00536C90 | 0.0% | Pending -SHC_3BB0A8C1_0x00536CC0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00536CC0 | 0.0% | Pending SHC_3BB0A8C1_0x00536CF0 | 0.0% | Pending @@ -51221,17 +51221,17 @@ SHC_3BB0A8C1_0x00536E30 | 0.0% | Pending SHC_3BB0A8C1_0x00537070 | 0.0% | Pending -SHC_3BB0A8C1_0x005370C0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x005370C0 | 0.0% | Pending -SHC_3BB0A8C1_0x00537100 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00537100 | 0.0% | Pending -SHC_3BB0A8C1_0x00537130 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00537130 | 0.0% | Pending -SHC_3BB0A8C1_0x00537160 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x00537160 | 0.0% | Pending SHC_3BB0A8C1_0x005371A0 | 0.0% | Pending -SHC_3BB0A8C1_0x005371E0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x005371E0 | 0.0% | Pending SHC_3BB0A8C1_0x005371F0 | 0.0% | Pending @@ -59625,9 +59625,9 @@ SHC_3BB0A8C1_0x0053B210 | 0.0% | Pending SHC_3BB0A8C1_0x0053B260 | 0.0% | Pending -SHC_3BB0A8C1_0x0053B310 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x0053B310 | 0.0% | Pending -SHC_3BB0A8C1_0x0053B340 | 90.91% | jne vs jl due to loop unroll prevention via != +SHC_3BB0A8C1_0x0053B340 | 0.0% | Pending SHC_3BB0A8C1_0x0053B380 | 0.0% | Pending @@ -59637,25 +59637,25 @@ SHC_3BB0A8C1_0x0053B3E0 | 0.0% | Pending SHC_3BB0A8C1_0x0053B4F0 | 0.0% | Pending -SHC_3BB0A8C1_0x0053B530 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x0053B530 | 0.0% | Pending -SHC_3BB0A8C1_0x0053B570 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x0053B570 | 0.0% | Pending SHC_3BB0A8C1_0x0053B5A0 | 0.0% | Pending -SHC_3BB0A8C1_0x0053B5E0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x0053B5E0 | 0.0% | Pending SHC_3BB0A8C1_0x0053B610 | 0.0% | Pending SHC_3BB0A8C1_0x0053B800 | 0.0% | Pending -SHC_3BB0A8C1_0x0053B8B0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x0053B8B0 | 0.0% | Pending SHC_3BB0A8C1_0x0053B8E0 | 0.0% | Pending SHC_3BB0A8C1_0x0053BB10 | 0.0% | Pending -SHC_3BB0A8C1_0x0053BB70 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x0053BB70 | 0.0% | Pending SHC_3BB0A8C1_0x0053BB90 | 0.0% | Pending @@ -59669,7 +59669,7 @@ SHC_3BB0A8C1_0x0053C400 | 0.0% | Pending SHC_3BB0A8C1_0x0053C590 | 0.0% | Pending -SHC_3BB0A8C1_0x0053CAC0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x0053CAC0 | 0.0% | Pending SHC_3BB0A8C1_0x0053CAE0 | 0.0% | Pending @@ -60095,7 +60095,7 @@ SHC_3BB0A8C1_0x0053E820 | 0.0% | Pending SHC_3BB0A8C1_0x0053E870 | 0.0% | Pending -SHC_3BB0A8C1_0x0053E8D0 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x0053E8D0 | 0.0% | Pending SHC_3BB0A8C1_0x0053E900 | 0.0% | Pending @@ -60107,12 +60107,8 @@ SHC_3BB0A8C1_0x0053F07C | 0.0% | Pending SHC_3BB0A8C1_0x0053F084 | 0.0% | Pending -SHC_3BB0A8C1_0x0053F088 | 0.0% | Pending - SHC_3BB0A8C1_0x0053F08F | 0.0% | Pending -SHC_3BB0A8C1_0x0053F09C | 0.0% | Pending - SHC_3BB0A8C1_0x0053F0AA | 0.0% | Pending SHC_3BB0A8C1_0x0053F0BA | 0.0% | Pending @@ -67547,7 +67543,7 @@ SHC_3BB0A8C1_0x0057B9BE | 0.0% | Pending SHC_3BB0A8C1_0x0057B9C0 | 0.0% | Pending -SHC_3BB0A8C1_0x0057BE10 | 100.0% | Reimplemented +SHC_3BB0A8C1_0x0057BE10 | 0.0% | Pending SHC_3BB0A8C1_0x0057C815 | 0.0% | Pending @@ -68325,7 +68321,7 @@ SHC_3BB0A8C1_0x00584001 | 0.0% | Pending SHC_3BB0A8C1_0x0058401B | 0.0% | Pending -SHC_3BB0A8C1_0x00584026 | 0.0% | instruction selection differs +SHC_3BB0A8C1_0x00584026 | 0.0% | Pending SHC_3BB0A8C1_0x00584030 | 0.0% | Pending @@ -86289,14 +86285,34 @@ SHC_3BB0A8C1_0x00EE2350 | 0.0% | Pending SHC_3BB0A8C1_0x00EE2354 | 0.0% | Pending +SHC_3BB0A8C1_0x00EE2358 | 0.0% | Pending + +SHC_3BB0A8C1_0x00EE235C | 0.0% | Pending + +SHC_3BB0A8C1_0x00EE2360 | 0.0% | Pending + SHC_3BB0A8C1_0x00EE2364 | 0.0% | Pending SHC_3BB0A8C1_0x00EE2368 | 0.0% | Pending +SHC_3BB0A8C1_0x00EE236C | 0.0% | Pending + +SHC_3BB0A8C1_0x00EE2370 | 0.0% | Pending + SHC_3BB0A8C1_0x00EE2374 | 0.0% | Pending +SHC_3BB0A8C1_0x00EE2378 | 0.0% | Pending + +SHC_3BB0A8C1_0x00EE237C | 0.0% | Pending + SHC_3BB0A8C1_0x00EE2380 | 0.0% | Pending +SHC_3BB0A8C1_0x00EE2384 | 0.0% | Pending + +SHC_3BB0A8C1_0x00EE2388 | 0.0% | Pending + +SHC_3BB0A8C1_0x00EE238C | 0.0% | Pending + SHC_3BB0A8C1_0x00EE2390 | 0.0% | Pending SHC_3BB0A8C1_0x00EE2394 | 0.0% | Pending diff --git a/tools/reimplementation-helper/batch/quick_diff.py b/tools/reimplementation-helper/batch/quick_diff.py index ab36a2bdd..6b027b95e 100644 --- a/tools/reimplementation-helper/batch/quick_diff.py +++ b/tools/reimplementation-helper/batch/quick_diff.py @@ -37,7 +37,8 @@ ENV['PATH'] = os.path.join(ROOT, 'MSVC1400-SP1', 'Common7', 'IDE') + os.pathsep + ENV['PATH'] cc = json.load(open('build-RelWithDebInfo/compile_commands.json')) base = [e for e in cc if 'OpenSHC.dll.dir' in e['command'] and '/src/OpenSHC/' in e['file'].replace(chr(92), '/')][0] -out = ROOT + '/build-RelWithDebInfo/batch/quick' +# QD_OUT picks the output folder, so concurrent runs (quick_reorder.py) do not share x.asm +out = ROOT + '/build-RelWithDebInfo/batch/' + os.environ.get('QD_OUT', 'quick') os.makedirs(out, exist_ok=True) d = open('_original/Stronghold Crusader.exe', 'rb').read()