From f541ae6f2b7ee7bca086dab1d54169e8c998470a Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 02:26:41 +0200 Subject: [PATCH 001/299] reimplement: SHC_3BB0A8C1_0x00535550 100.00% Reimplemented --- .../Map/Units/UnitsState/selectionHasEngineers.cpp | 12 ++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/selectionHasEngineers.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/selectionHasEngineers.cpp b/src/OpenSHC/Map/Units/UnitsState/selectionHasEngineers.cpp new file mode 100644 index 000000000..6f6f29301 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/selectionHasEngineers.cpp @@ -0,0 +1,12 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + // FUNCTION: STRONGHOLDCRUSADER 0x00535550 + BOOLEnum UnitsState::selectionHasEngineers() { return (BOOLEnum)(this->selectionEngineers != 0); } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index b80b8635f..edf9c42e8 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -51067,7 +51067,7 @@ SHC_3BB0A8C1_0x00535514 | 0.0% | Pending SHC_3BB0A8C1_0x00535520 | 0.0% | Pending -SHC_3BB0A8C1_0x00535550 | 0.0% | Pending +SHC_3BB0A8C1_0x00535550 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00535560 | 0.0% | Pending From 2760f4a1c58bf37fa98d446211418efaadd1806d Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:43:56 +0200 Subject: [PATCH 002/299] reimplement: SHC_3BB0A8C1_0x005339F0 100.00% Reimplemented --- .../UnitsState/hasTunnelerNotFinishedDigging.cpp | 15 +++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/hasTunnelerNotFinishedDigging.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/hasTunnelerNotFinishedDigging.cpp b/src/OpenSHC/Map/Units/UnitsState/hasTunnelerNotFinishedDigging.cpp new file mode 100644 index 000000000..c59ce47e4 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/hasTunnelerNotFinishedDigging.cpp @@ -0,0 +1,15 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + // FUNCTION: STRONGHOLDCRUSADER 0x005339F0 + BOOLEnum UnitsState::hasTunnelerNotFinishedDigging(int unitID) + { + return (BOOLEnum)(this->units[unitID].tunnelerFinishedDigging == 0); + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index edf9c42e8..bb291fc35 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -50683,7 +50683,7 @@ SHC_3BB0A8C1_0x00533960 | 0.0% | Pending SHC_3BB0A8C1_0x005339A0 | 0.0% | Pending -SHC_3BB0A8C1_0x005339F0 | 0.0% | Pending +SHC_3BB0A8C1_0x005339F0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00533A10 | 0.0% | Pending From f0937b1b4df6c705f32a673f6a9011196d939529 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:43:56 +0200 Subject: [PATCH 003/299] reimplement: SHC_3BB0A8C1_0x00532F60 100.00% Reimplemented --- src/OpenSHC/Map/Units/UnitsState/getArmySize.cpp | 14 ++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/getArmySize.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/getArmySize.cpp b/src/OpenSHC/Map/Units/UnitsState/getArmySize.cpp new file mode 100644 index 000000000..9f0b04ebf --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/getArmySize.cpp @@ -0,0 +1,14 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" + +#include "OpenSHC/Globals/DAT_GameState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + // FUNCTION: STRONGHOLDCRUSADER 0x00532F60 + int UnitsState::getArmySize(int playerID) { return DAT_GameState::instance.playerDataArray[playerID].armySize; } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index bb291fc35..83d95a1c3 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -50643,7 +50643,7 @@ SHC_3BB0A8C1_0x00532F5D | 0.0% | Pending SHC_3BB0A8C1_0x00532F5E | 0.0% | Pending -SHC_3BB0A8C1_0x00532F60 | 0.0% | Pending +SHC_3BB0A8C1_0x00532F60 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00532F80 | 0.0% | Pending From 42842ea4c7c96a87a8abfd342c94c048e779d060 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:43:56 +0200 Subject: [PATCH 004/299] reimplement: SHC_3BB0A8C1_0x00533090 100.00% Reimplemented --- .../Map/Units/UnitsState/returnFalseStub.cpp | 15 +++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/returnFalseStub.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/returnFalseStub.cpp b/src/OpenSHC/Map/Units/UnitsState/returnFalseStub.cpp new file mode 100644 index 000000000..a23bf4e6d --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/returnFalseStub.cpp @@ -0,0 +1,15 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x00533090 + BOOLEnum UnitsState::returnFalseStub(int unitID) { return FALSE; } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 83d95a1c3..e8e1fe575 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -50649,7 +50649,7 @@ SHC_3BB0A8C1_0x00532F80 | 0.0% | Pending SHC_3BB0A8C1_0x00533010 | 0.0% | Pending -SHC_3BB0A8C1_0x00533090 | 0.0% | Pending +SHC_3BB0A8C1_0x00533090 | 100.0% | Reimplemented SHC_3BB0A8C1_0x005330A0 | 0.0% | Pending From 4c8ee79fb68c7fd9f8b7939c48ec97123e40693e Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:43:57 +0200 Subject: [PATCH 005/299] reimplement: SHC_3BB0A8C1_0x00535190 100.00% Reimplemented --- .../Map/Units/UnitsState/deselectUnit.cpp | 19 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/deselectUnit.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/deselectUnit.cpp b/src/OpenSHC/Map/Units/UnitsState/deselectUnit.cpp new file mode 100644 index 000000000..db8e9ebcd --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/deselectUnit.cpp @@ -0,0 +1,19 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + // FUNCTION: STRONGHOLDCRUSADER 0x00535190 + void UnitsState::deselectUnit(int unitID) + { + if (this->units[unitID].isSelected == 0) { + return; + } + this->units[unitID].isSelected = 0; + this->totalUnitsInSelection = this->totalUnitsInSelection - 1; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index e8e1fe575..fe87d1247 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -50857,7 +50857,7 @@ SHC_3BB0A8C1_0x005350B0 | 0.0% | Pending SHC_3BB0A8C1_0x00535150 | 0.0% | Pending -SHC_3BB0A8C1_0x00535190 | 0.0% | Pending +SHC_3BB0A8C1_0x00535190 | 100.0% | Reimplemented SHC_3BB0A8C1_0x005351C0 | 0.0% | Pending From f6497b9375bfc19ac2e86a5c106754a36df37280 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:43:57 +0200 Subject: [PATCH 006/299] reimplement: SHC_3BB0A8C1_0x0053BB70 100.00% Reimplemented --- .../setupUnitSharingCurrentTilePosition.cpp | 16 ++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/setupUnitSharingCurrentTilePosition.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/setupUnitSharingCurrentTilePosition.cpp b/src/OpenSHC/Map/Units/UnitsState/setupUnitSharingCurrentTilePosition.cpp new file mode 100644 index 000000000..6e4377aac --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/setupUnitSharingCurrentTilePosition.cpp @@ -0,0 +1,16 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + // FUNCTION: STRONGHOLDCRUSADER 0x0053BB70 + void UnitsState::setupUnitSharingCurrentTilePosition(int unitID) + { + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::setupUnitSharingTileIDs, this)( + unitID, this->units[unitID].tile); + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index fe87d1247..4bee0ab3f 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -59655,7 +59655,7 @@ SHC_3BB0A8C1_0x0053B8E0 | 0.0% | Pending SHC_3BB0A8C1_0x0053BB10 | 0.0% | Pending -SHC_3BB0A8C1_0x0053BB70 | 0.0% | Pending +SHC_3BB0A8C1_0x0053BB70 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0053BB90 | 0.0% | Pending From 4bad493403a8b5538503dc4344046fd774b7e63d Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:43:58 +0200 Subject: [PATCH 007/299] reimplement: SHC_3BB0A8C1_0x00533F90 100.00% Reimplemented --- .../saveUnitStateBeforeInterruption.cpp | 17 +++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/saveUnitStateBeforeInterruption.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/saveUnitStateBeforeInterruption.cpp b/src/OpenSHC/Map/Units/UnitsState/saveUnitStateBeforeInterruption.cpp new file mode 100644 index 000000000..6c0d666bb --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/saveUnitStateBeforeInterruption.cpp @@ -0,0 +1,17 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + // FUNCTION: STRONGHOLDCRUSADER 0x00533F90 + void UnitsState::saveUnitStateBeforeInterruption(int unitID) + { + UnitStateUnion _savedState = this->units[unitID].state; + this->units[unitID].tunnelerFinishedDigging = 5; + this->units[unitID].state_3 = _savedState; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 4bee0ab3f..c82e066ca 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -50777,7 +50777,7 @@ SHC_3BB0A8C1_0x00533F84 | 0.0% | Pending SHC_3BB0A8C1_0x00533F85 | 0.0% | Pending -SHC_3BB0A8C1_0x00533F90 | 0.0% | Pending +SHC_3BB0A8C1_0x00533F90 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00533FC0 | 0.0% | Pending From 23de6f913fdfaf52bf91ecf3f71353cd4d2084b7 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:43:58 +0200 Subject: [PATCH 008/299] reimplement: SHC_3BB0A8C1_0x005311F0 100.00% Reimplemented --- .../UnitsState/computeDamageFearFactorBonus.cpp | 17 +++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/computeDamageFearFactorBonus.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/computeDamageFearFactorBonus.cpp b/src/OpenSHC/Map/Units/UnitsState/computeDamageFearFactorBonus.cpp new file mode 100644 index 000000000..6868e49ac --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/computeDamageFearFactorBonus.cpp @@ -0,0 +1,17 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" + +#include "OpenSHC/Globals/DAT_GameState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + // FUNCTION: STRONGHOLDCRUSADER 0x005311F0 + int UnitsState::computeDamageFearFactorBonus(int damage, int playerID) + { + return ((DAT_GameState::instance.playerDataArray[playerID].fearFactorLevel + 20) * damage * 5) / 100; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index c82e066ca..865ddf6d9 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -49663,7 +49663,7 @@ SHC_3BB0A8C1_0x00530FD0 | 0.0% | Pending SHC_3BB0A8C1_0x00531000 | 0.0% | Pending -SHC_3BB0A8C1_0x005311F0 | 0.0% | Pending +SHC_3BB0A8C1_0x005311F0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00531220 | 0.0% | Pending From 54dd57857dfc2e4f0cf92e854e5bd31f6caaaf60 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:43:58 +0200 Subject: [PATCH 009/299] reimplement: SHC_3BB0A8C1_0x00535560 100.00% Reimplemented --- .../Units/UnitsState/selectionHasArchers.cpp | 21 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/selectionHasArchers.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/selectionHasArchers.cpp b/src/OpenSHC/Map/Units/UnitsState/selectionHasArchers.cpp new file mode 100644 index 000000000..174d7be44 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/selectionHasArchers.cpp @@ -0,0 +1,21 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x00535560 + BOOLEnum UnitsState::selectionHasArchers() + { + if (this->selectionEuropeanArchers != 0) { + return TRUE; + } + return (BOOLEnum)(this->selectionArabArcher != 0); + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 865ddf6d9..f1d9306af 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -51069,7 +51069,7 @@ SHC_3BB0A8C1_0x00535520 | 0.0% | Pending SHC_3BB0A8C1_0x00535550 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x00535560 | 0.0% | Pending +SHC_3BB0A8C1_0x00535560 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00535580 | 0.0% | Pending From d1f97fff291cb908458a49aefb0e7043d3ea845f Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:43:59 +0200 Subject: [PATCH 010/299] reimplement: SHC_3BB0A8C1_0x0052F0A0 100.00% Reimplemented --- .../checkUnitHasPropertyBasedOnUnitType.cpp | 18 ++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/checkUnitHasPropertyBasedOnUnitType.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/checkUnitHasPropertyBasedOnUnitType.cpp b/src/OpenSHC/Map/Units/UnitsState/checkUnitHasPropertyBasedOnUnitType.cpp new file mode 100644 index 000000000..41fe38a6f --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/checkUnitHasPropertyBasedOnUnitType.cpp @@ -0,0 +1,18 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" + +#include "OpenSHC/Globals/DAT_UnitPropertiesDefinedData.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + // FUNCTION: STRONGHOLDCRUSADER 0x0052F0A0 + int UnitsState::checkUnitHasPropertyBasedOnUnitType(int unitID, int property) + { + return DAT_UnitPropertiesDefinedData::instance + .UnitClimbStateFlags[property][(short)this->units[unitID].unitType]; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index f1d9306af..8f6d725ec 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -49319,7 +49319,7 @@ SHC_3BB0A8C1_0x0052F010 | 0.0% | Pending SHC_3BB0A8C1_0x0052F070 | 0.0% | Pending -SHC_3BB0A8C1_0x0052F0A0 | 0.0% | Pending +SHC_3BB0A8C1_0x0052F0A0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0052F0D0 | 0.0% | Pending From 48bfc2232e88e01f4280408c96e49bf6c282cbea Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:43:59 +0200 Subject: [PATCH 011/299] reimplement: SHC_3BB0A8C1_0x00534460 100.00% Reimplemented --- .../Map/Units/UnitsState/unitIsInMoat.cpp | 17 +++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/unitIsInMoat.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/unitIsInMoat.cpp b/src/OpenSHC/Map/Units/UnitsState/unitIsInMoat.cpp new file mode 100644 index 000000000..ea3efa200 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/unitIsInMoat.cpp @@ -0,0 +1,17 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" + +#include "OpenSHC/Globals/DAT_TileMapState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + // FUNCTION: STRONGHOLDCRUSADER 0x00534460 + BOOLEnum UnitsState::unitIsInMoat(int unitID) + { + return (BOOLEnum)((uint)DAT_TileMapState::instance.LogicLayer[this->units[unitID].tile] >> 30 & 1); + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 8f6d725ec..e101f4fa1 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -50809,7 +50809,7 @@ SHC_3BB0A8C1_0x005343C0 | 0.0% | Pending SHC_3BB0A8C1_0x005343F0 | 0.0% | Pending -SHC_3BB0A8C1_0x00534460 | 0.0% | Pending +SHC_3BB0A8C1_0x00534460 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00534490 | 0.0% | Pending From ce0bafd30d021d1d5027ccf6dd38c2b421d16b83 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:43:59 +0200 Subject: [PATCH 012/299] reimplement: SHC_3BB0A8C1_0x0052F070 100.00% Reimplemented --- ...tStopWalkingByClearingPathProgressState.cpp | 18 ++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/makeUnitStopWalkingByClearingPathProgressState.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/makeUnitStopWalkingByClearingPathProgressState.cpp b/src/OpenSHC/Map/Units/UnitsState/makeUnitStopWalkingByClearingPathProgressState.cpp new file mode 100644 index 000000000..37662395b --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/makeUnitStopWalkingByClearingPathProgressState.cpp @@ -0,0 +1,18 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + // FUNCTION: STRONGHOLDCRUSADER 0x0052F070 + void UnitsState::makeUnitStopWalkingByClearingPathProgressState(int unitID) + { + this->units[unitID].currentIndexInPathPlan = 0; + this->units[unitID].totalSizeOfPathPlan = 0; + this->units[unitID].unknownMovementRelated_0x2d2 = 0; + this->units[unitID].climbDataID = 0; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index e101f4fa1..cc9f536cd 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -49317,7 +49317,7 @@ SHC_3BB0A8C1_0x0052EED0 | 0.0% | Pending SHC_3BB0A8C1_0x0052F010 | 0.0% | Pending -SHC_3BB0A8C1_0x0052F070 | 0.0% | Pending +SHC_3BB0A8C1_0x0052F070 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0052F0A0 | 100.0% | Reimplemented From cc2e02274afd181a6824fa2f3a782d691caa717f Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:00 +0200 Subject: [PATCH 013/299] reimplement: SHC_3BB0A8C1_0x00533C70 100.00% Reimplemented --- .../UnitsState/changeDestinationByLeftover.cpp | 18 ++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/changeDestinationByLeftover.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/changeDestinationByLeftover.cpp b/src/OpenSHC/Map/Units/UnitsState/changeDestinationByLeftover.cpp new file mode 100644 index 000000000..e38e18463 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/changeDestinationByLeftover.cpp @@ -0,0 +1,18 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + // FUNCTION: STRONGHOLDCRUSADER 0x00533C70 + void UnitsState::changeDestinationByLeftover(int unitID) + { + if (this->units[unitID].leftover > 0) { + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::changeDestinationByAmount, this)( + unitID, this->units[unitID].leftover); + } + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index cc9f536cd..23be6b555 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -50689,7 +50689,7 @@ SHC_3BB0A8C1_0x00533A10 | 0.0% | Pending SHC_3BB0A8C1_0x00533B30 | 0.0% | Pending -SHC_3BB0A8C1_0x00533C70 | 0.0% | Pending +SHC_3BB0A8C1_0x00533C70 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00533CA0 | 0.0% | Pending From 10697f79cc5c6ec72b027dfdf1a8e0f8b2708596 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:00 +0200 Subject: [PATCH 014/299] reimplement: SHC_3BB0A8C1_0x0053E8D0 100.00% Reimplemented --- .../clearHiddenFlagAndUpdatePosition.cpp | 19 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/clearHiddenFlagAndUpdatePosition.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/clearHiddenFlagAndUpdatePosition.cpp b/src/OpenSHC/Map/Units/UnitsState/clearHiddenFlagAndUpdatePosition.cpp new file mode 100644 index 000000000..642cf55a6 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/clearHiddenFlagAndUpdatePosition.cpp @@ -0,0 +1,19 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + // FUNCTION: STRONGHOLDCRUSADER 0x0053E8D0 + void UnitsState::clearHiddenFlagAndUpdatePosition(int unitID) + { + if (this->units[unitID].unknownTestAgainst0_2 == 0) { + return; + } + this->units[unitID].unknownTestAgainst0_2 = 0; + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::commitPendingUnitPosition, this)(unitID); + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 23be6b555..77552ee7c 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -60095,7 +60095,7 @@ SHC_3BB0A8C1_0x0053E820 | 0.0% | Pending SHC_3BB0A8C1_0x0053E870 | 0.0% | Pending -SHC_3BB0A8C1_0x0053E8D0 | 0.0% | Pending +SHC_3BB0A8C1_0x0053E8D0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0053E900 | 0.0% | Pending From e4bf08b819100f0948595a4cc70e10c30202ccf4 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:01 +0200 Subject: [PATCH 015/299] reimplement: SHC_3BB0A8C1_0x0053B8B0 100.00% Reimplemented --- .../UnitsState/Constructor_UnitsState.cpp | 21 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/Constructor_UnitsState.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/Constructor_UnitsState.cpp b/src/OpenSHC/Map/Units/UnitsState/Constructor_UnitsState.cpp new file mode 100644 index 000000000..849750f99 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/Constructor_UnitsState.cpp @@ -0,0 +1,21 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + // FUNCTION: STRONGHOLDCRUSADER 0x0053B8B0 + UnitsState* UnitsState::Constructor_UnitsState() + { + this->creationTime = timeGetTime(); + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::clearAllUnits, this)(); + this->lastSelectedUnitID = 0; + this->unknownInitially0_01 = 0; + this->lostChimps = 0; + this->maxUnitCount = 2500; + return this; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 77552ee7c..1776db81e 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -59649,7 +59649,7 @@ SHC_3BB0A8C1_0x0053B610 | 0.0% | Pending SHC_3BB0A8C1_0x0053B800 | 0.0% | Pending -SHC_3BB0A8C1_0x0053B8B0 | 0.0% | Pending +SHC_3BB0A8C1_0x0053B8B0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0053B8E0 | 0.0% | Pending From 510dfee862948238b4e55071e2aea5264bf6abdd Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:01 +0200 Subject: [PATCH 016/299] reimplement: SHC_3BB0A8C1_0x0052FBB0 100.00% Reimplemented --- .../Map/Units/UnitsState/standUpIfSeated.cpp | 23 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/standUpIfSeated.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/standUpIfSeated.cpp b/src/OpenSHC/Map/Units/UnitsState/standUpIfSeated.cpp new file mode 100644 index 000000000..490b14fc3 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/standUpIfSeated.cpp @@ -0,0 +1,23 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x0052FBB0 + BOOLEnum UnitsState::standUpIfSeated(int unitID) + { + if (this->units[unitID].seated == 0) { + return FALSE; + } + this->units[unitID].substate = 100; + this->units[unitID].animationCycleNumber = 0; + return TRUE; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 1776db81e..aecc235c1 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -49345,7 +49345,7 @@ SHC_3BB0A8C1_0x0052F730 | 0.0% | Pending SHC_3BB0A8C1_0x0052F7E0 | 0.0% | Pending -SHC_3BB0A8C1_0x0052FBB0 | 0.0% | Pending +SHC_3BB0A8C1_0x0052FBB0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0052FBF0 | 0.0% | Pending From 5cb96c3043cad653564879b2e9672e340fc82960 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:01 +0200 Subject: [PATCH 017/299] reimplement: SHC_3BB0A8C1_0x0052FBF0 100.00% Reimplemented --- .../Units/UnitsState/sitDownIfStanding.cpp | 23 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/sitDownIfStanding.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/sitDownIfStanding.cpp b/src/OpenSHC/Map/Units/UnitsState/sitDownIfStanding.cpp new file mode 100644 index 000000000..8c58add10 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/sitDownIfStanding.cpp @@ -0,0 +1,23 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x0052FBF0 + BOOLEnum UnitsState::sitDownIfStanding(int unitID) + { + if (this->units[unitID].seated != 0) { + return FALSE; + } + this->units[unitID].substate = 101; + this->units[unitID].animationCycleNumber = 0; + return TRUE; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index aecc235c1..3b014f6b3 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -49347,7 +49347,7 @@ SHC_3BB0A8C1_0x0052F7E0 | 0.0% | Pending SHC_3BB0A8C1_0x0052FBB0 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x0052FBF0 | 0.0% | Pending +SHC_3BB0A8C1_0x0052FBF0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0052FC30 | 0.0% | Pending From 8423dd2193528e2b98afe4b8c2be23ab5b4e22ee Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:02 +0200 Subject: [PATCH 018/299] reimplement: SHC_3BB0A8C1_0x00533920 100.00% Reimplemented --- .../getDestination2EqualsGivenCoordinates.cpp | 21 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/getDestination2EqualsGivenCoordinates.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/getDestination2EqualsGivenCoordinates.cpp b/src/OpenSHC/Map/Units/UnitsState/getDestination2EqualsGivenCoordinates.cpp new file mode 100644 index 000000000..5fac9ac47 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/getDestination2EqualsGivenCoordinates.cpp @@ -0,0 +1,21 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x00533920 + BOOLEnum UnitsState::getDestination2EqualsGivenCoordinates(int unitID, int x, int y) + { + if (this->units[unitID].destinationX_2Unk != x) { + return TRUE; + } + return (BOOLEnum)(this->units[unitID].destinationY_2Unk != y); + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 3b014f6b3..a69254dd7 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -50677,7 +50677,7 @@ SHC_3BB0A8C1_0x00533630 | 0.0% | Pending SHC_3BB0A8C1_0x00533810 | 0.0% | Pending -SHC_3BB0A8C1_0x00533920 | 0.0% | Pending +SHC_3BB0A8C1_0x00533920 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00533960 | 0.0% | Pending From 7f13d1102d70a91302c5597975e56c10e3667b5d Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:02 +0200 Subject: [PATCH 019/299] reimplement: SHC_3BB0A8C1_0x0054A770 100.00% Reimplemented --- .../resumeMovementIfNoAttackTarget.cpp | 20 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/resumeMovementIfNoAttackTarget.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/resumeMovementIfNoAttackTarget.cpp b/src/OpenSHC/Map/Units/UnitsState/resumeMovementIfNoAttackTarget.cpp new file mode 100644 index 000000000..a2b57349a --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/resumeMovementIfNoAttackTarget.cpp @@ -0,0 +1,20 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + // FUNCTION: STRONGHOLDCRUSADER 0x0054A770 + void UnitsState::resumeMovementIfNoAttackTarget(int unitID) + { + if (this->units[unitID].attackedUnitID != 0) { + return; + } + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::resumeMovementAfterInterruption, this)(unitID); + this->units[unitID].attackedUnitID = 0; + this->units[unitID].field191_0x340 = 0; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index a69254dd7..659cb5432 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -61407,7 +61407,7 @@ SHC_3BB0A8C1_0x00549B30 | 0.0% | Pending SHC_3BB0A8C1_0x00549C70 | 0.0% | Pending -SHC_3BB0A8C1_0x0054A770 | 0.0% | Pending +SHC_3BB0A8C1_0x0054A770 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0054A7B0 | 0.0% | Pending From 3277049c8458b12ba04d0a6710e66dd3f69bdda9 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:02 +0200 Subject: [PATCH 020/299] reimplement: SHC_3BB0A8C1_0x00535840 100.00% Reimplemented --- .../selectionContainsShieldmenOnly.cpp | 23 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/selectionContainsShieldmenOnly.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/selectionContainsShieldmenOnly.cpp b/src/OpenSHC/Map/Units/UnitsState/selectionContainsShieldmenOnly.cpp new file mode 100644 index 000000000..89ced34e6 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/selectionContainsShieldmenOnly.cpp @@ -0,0 +1,23 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + // FUNCTION: STRONGHOLDCRUSADER 0x00535840 + int UnitsState::selectionContainsShieldmenOnly() + { + if (this->selectionShield == 0) { + return 0; + } + for (int i = 0; i <= 26; ++i) { + if (i != 15 && (&this->selectionEuropeanArchers)[i] != 0) { + return 0; + } + } + return 1; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 659cb5432..7fd7ef3cc 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -51085,7 +51085,7 @@ SHC_3BB0A8C1_0x005357E0 | 0.0% | Pending SHC_3BB0A8C1_0x00535810 | 0.0% | Pending -SHC_3BB0A8C1_0x00535840 | 0.0% | Pending +SHC_3BB0A8C1_0x00535840 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00535870 | 0.0% | Pending From eb96e73b6703167137303d9f1e9a3a474d3a10f6 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:03 +0200 Subject: [PATCH 021/299] reimplement: SHC_3BB0A8C1_0x005357E0 100.00% Reimplemented --- .../selectionContainsLaddermenOnly.cpp | 23 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/selectionContainsLaddermenOnly.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/selectionContainsLaddermenOnly.cpp b/src/OpenSHC/Map/Units/UnitsState/selectionContainsLaddermenOnly.cpp new file mode 100644 index 000000000..7ff5ac8bb --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/selectionContainsLaddermenOnly.cpp @@ -0,0 +1,23 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + // FUNCTION: STRONGHOLDCRUSADER 0x005357E0 + int UnitsState::selectionContainsLaddermenOnly() + { + if (this->selectionLaddermen == 0) { + return 0; + } + for (int i = 0; i <= 26; ++i) { + if (i != 8 && (&this->selectionEuropeanArchers)[i] != 0) { + return 0; + } + } + return 1; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 7fd7ef3cc..971038b01 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -51081,7 +51081,7 @@ SHC_3BB0A8C1_0x00535700 | 0.0% | Pending SHC_3BB0A8C1_0x00535730 | 0.0% | Pending -SHC_3BB0A8C1_0x005357E0 | 0.0% | Pending +SHC_3BB0A8C1_0x005357E0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00535810 | 0.0% | Pending From af08966c947c6a0fdbabbeb444408bcc0dab2ad8 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:03 +0200 Subject: [PATCH 022/299] reimplement: SHC_3BB0A8C1_0x00535700 100.00% Reimplemented --- .../selectionContainsTunnelersOnly.cpp | 23 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/selectionContainsTunnelersOnly.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/selectionContainsTunnelersOnly.cpp b/src/OpenSHC/Map/Units/UnitsState/selectionContainsTunnelersOnly.cpp new file mode 100644 index 000000000..5f7dfbb1a --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/selectionContainsTunnelersOnly.cpp @@ -0,0 +1,23 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + // FUNCTION: STRONGHOLDCRUSADER 0x00535700 + int UnitsState::selectionContainsTunnelersOnly() + { + if (this->selectionTunnelers == 0) { + return 0; + } + for (int i = 0; i <= 26; ++i) { + if (i != 9 && (&this->selectionEuropeanArchers)[i] != 0) { + return 0; + } + } + return 1; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 971038b01..092466fe1 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -51077,7 +51077,7 @@ SHC_3BB0A8C1_0x005355E0 | 0.0% | Pending SHC_3BB0A8C1_0x00535680 | 0.0% | Pending -SHC_3BB0A8C1_0x00535700 | 0.0% | Pending +SHC_3BB0A8C1_0x00535700 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00535730 | 0.0% | Pending From 8aaa9248a7098234ed9a9068a0c371d5df590a46 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:04 +0200 Subject: [PATCH 023/299] reimplement: SHC_3BB0A8C1_0x00535980 100.00% Reimplemented --- .../UnitsState/selectionHasFootSoldiers.cpp | 19 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/selectionHasFootSoldiers.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/selectionHasFootSoldiers.cpp b/src/OpenSHC/Map/Units/UnitsState/selectionHasFootSoldiers.cpp new file mode 100644 index 000000000..5f36b0d57 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/selectionHasFootSoldiers.cpp @@ -0,0 +1,19 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + // FUNCTION: STRONGHOLDCRUSADER 0x00535980 + undefined4 UnitsState::selectionHasFootSoldiers() + { + if (this->selectionEngineers == 0 && this->selectionArabSlave == 0 && this->selectionSpearmen == 0 + && this->selectionEuropeanArchers == 0 && this->selectionMacemen == 0 && this->selectionPikemen == 0) { + return 0; + } + return 1; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 092466fe1..5869ea387 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -51093,7 +51093,7 @@ SHC_3BB0A8C1_0x005358C0 | 0.0% | Pending SHC_3BB0A8C1_0x00535910 | 0.0% | Pending -SHC_3BB0A8C1_0x00535980 | 0.0% | Pending +SHC_3BB0A8C1_0x00535980 | 100.0% | Reimplemented SHC_3BB0A8C1_0x005359C0 | 0.0% | Pending From 856041bcdfe336f2f79e201d663035027232792d Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:04 +0200 Subject: [PATCH 024/299] reimplement: SHC_3BB0A8C1_0x00530FD0 100.00% Reimplemented --- .../checkIfCitizenUnitIsAliveBasedOnState.cpp | 22 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/checkIfCitizenUnitIsAliveBasedOnState.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/checkIfCitizenUnitIsAliveBasedOnState.cpp b/src/OpenSHC/Map/Units/UnitsState/checkIfCitizenUnitIsAliveBasedOnState.cpp new file mode 100644 index 000000000..ae3d0d8db --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/checkIfCitizenUnitIsAliveBasedOnState.cpp @@ -0,0 +1,22 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x00530FD0 + BOOLEnum UnitsState::checkIfCitizenUnitIsAliveBasedOnState(int unitID) + { + if ((short)this->units[unitID].state.generic >= States::US_DEATH_01 + && (short)this->units[unitID].state.generic <= States::US_STONE_DEATH_03) { + return TRUE; + } + return FALSE; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 5869ea387..cb78ed6d3 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -49659,7 +49659,7 @@ SHC_3BB0A8C1_0x00530EB0 | 0.0% | Pending SHC_3BB0A8C1_0x00530F20 | 0.0% | Pending -SHC_3BB0A8C1_0x00530FD0 | 0.0% | Pending +SHC_3BB0A8C1_0x00530FD0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00531000 | 0.0% | Pending From 686ebb09d0f3da21c6cc23cf6657be9d6a3f45a7 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:04 +0200 Subject: [PATCH 025/299] reimplement: SHC_3BB0A8C1_0x00533960 100.00% Reimplemented --- .../UnitsState/isAtSecondaryDestination.cpp | 21 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/isAtSecondaryDestination.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/isAtSecondaryDestination.cpp b/src/OpenSHC/Map/Units/UnitsState/isAtSecondaryDestination.cpp new file mode 100644 index 000000000..331d3b2c4 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/isAtSecondaryDestination.cpp @@ -0,0 +1,21 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x00533960 + BOOLEnum UnitsState::isAtSecondaryDestination(int unitID) + { + if (this->units[unitID].destinationX_2Unk != this->units[unitID].x) { + return FALSE; + } + return (BOOLEnum)(this->units[unitID].destinationY_2Unk == this->units[unitID].y); + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index cb78ed6d3..9037e4c7d 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -50679,7 +50679,7 @@ SHC_3BB0A8C1_0x00533810 | 0.0% | Pending SHC_3BB0A8C1_0x00533920 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x00533960 | 0.0% | Pending +SHC_3BB0A8C1_0x00533960 | 100.0% | Reimplemented SHC_3BB0A8C1_0x005339A0 | 0.0% | Pending From d8d3dd98fdbbf5eff0facd1ec6ac9e328fb4ed93 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:05 +0200 Subject: [PATCH 026/299] reimplement: SHC_3BB0A8C1_0x005358C0 100.00% Reimplemented --- .../selectionHasShieldOrSiegeTower.cpp | 23 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/selectionHasShieldOrSiegeTower.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/selectionHasShieldOrSiegeTower.cpp b/src/OpenSHC/Map/Units/UnitsState/selectionHasShieldOrSiegeTower.cpp new file mode 100644 index 000000000..19ce2c62b --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/selectionHasShieldOrSiegeTower.cpp @@ -0,0 +1,23 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + // FUNCTION: STRONGHOLDCRUSADER 0x005358C0 + undefined4 UnitsState::selectionHasShieldOrSiegeTower() + { + if (this->selectionShield != 0 || this->selectionSiegeTower != 0) { + for (int i = 0; i <= 26; ++i) { + if (i != 15 && i != 14 && (&this->selectionEuropeanArchers)[i] != 0) { + return 0; + } + } + return 1; + } + return 0; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 9037e4c7d..878ae4350 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -51089,7 +51089,7 @@ SHC_3BB0A8C1_0x00535840 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00535870 | 0.0% | Pending -SHC_3BB0A8C1_0x005358C0 | 0.0% | Pending +SHC_3BB0A8C1_0x005358C0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00535910 | 0.0% | Pending From 36085a74da1e537c077652ee2c4fd6186406821a Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:05 +0200 Subject: [PATCH 027/299] reimplement: SHC_3BB0A8C1_0x005371E0 100.00% Reimplemented --- .../UnitsState/relayTribeInstruction.cpp | 20 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/relayTribeInstruction.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/relayTribeInstruction.cpp b/src/OpenSHC/Map/Units/UnitsState/relayTribeInstruction.cpp new file mode 100644 index 000000000..e2e3b490f --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/relayTribeInstruction.cpp @@ -0,0 +1,20 @@ +#include "OpenSHC/Map/Units/TribesState.func.hpp" +#include "OpenSHC/Map/Units/UnitsState.func.hpp" + +#include "OpenSHC/Globals/DAT_TribesState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + // FUNCTION: STRONGHOLDCRUSADER 0x005371E0 + void UnitsState::relayTribeInstruction( + int tribeID, UnitInstructionType instructionType, int targetID_1, int targetID_2, int param_5) + { + MACRO_CALL_MEMBER(OpenSHC::Map::Units::TribesState_Func::giveTribeAnInstruction, DAT_TribesState::ptr)( + tribeID, instructionType, targetID_1, targetID_2, param_5); + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 878ae4350..c732b5be0 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -51231,7 +51231,7 @@ SHC_3BB0A8C1_0x00537160 | 0.0% | Pending SHC_3BB0A8C1_0x005371A0 | 0.0% | Pending -SHC_3BB0A8C1_0x005371E0 | 0.0% | Pending +SHC_3BB0A8C1_0x005371E0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x005371F0 | 0.0% | Pending From 3fd7e7040666037dffbdc102fcdab4f843fb08c8 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:05 +0200 Subject: [PATCH 028/299] reimplement: SHC_3BB0A8C1_0x00535580 100.00% Reimplemented --- .../selectionHasMobileAssaultUnits.cpp | 21 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/selectionHasMobileAssaultUnits.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/selectionHasMobileAssaultUnits.cpp b/src/OpenSHC/Map/Units/UnitsState/selectionHasMobileAssaultUnits.cpp new file mode 100644 index 000000000..3856a7400 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/selectionHasMobileAssaultUnits.cpp @@ -0,0 +1,21 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + // FUNCTION: STRONGHOLDCRUSADER 0x00535580 + undefined4 UnitsState::selectionHasMobileAssaultUnits() + { + if (this->selectionKnights == 0 && this->selectionLaddermen == 0 && this->selectionBatteringRam == 0 + && this->selectionTrebuchets == 0 && this->selectionCatapults == 0 + && this->selectionArabHorseArchers == 0 && this->selectionFireBallista == 0 + && this->selectionSiegeTower == 0) { + return 0; + } + return 1; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index c732b5be0..490bf4a10 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -51071,7 +51071,7 @@ SHC_3BB0A8C1_0x00535550 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00535560 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x00535580 | 0.0% | Pending +SHC_3BB0A8C1_0x00535580 | 100.0% | Reimplemented SHC_3BB0A8C1_0x005355E0 | 0.0% | Pending From fd657b9c5e6a8fa49800dfb78fc7cda3069e653d Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:06 +0200 Subject: [PATCH 029/299] reimplement: SHC_3BB0A8C1_0x005339A0 100.00% Reimplemented --- .../UnitsState/hasUnitReachedDestination.cpp | 29 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/hasUnitReachedDestination.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/hasUnitReachedDestination.cpp b/src/OpenSHC/Map/Units/UnitsState/hasUnitReachedDestination.cpp new file mode 100644 index 000000000..861e4fb3c --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/hasUnitReachedDestination.cpp @@ -0,0 +1,29 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x005339A0 + BOOLEnum UnitsState::hasUnitReachedDestination(int unitID) + { + if (this->units[unitID].tunnelerFinishedDigging != 0) { + return FALSE; + } + if (this->units[unitID].climbDataID != 0) { + if (this->units[unitID].destinationX_2Unk != this->units[unitID].x) { + return FALSE; + } + if (this->units[unitID].destinationY_2Unk != this->units[unitID].y) { + return FALSE; + } + } + return TRUE; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 490bf4a10..4d12b75cb 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -50681,7 +50681,7 @@ SHC_3BB0A8C1_0x00533920 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00533960 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x005339A0 | 0.0% | Pending +SHC_3BB0A8C1_0x005339A0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x005339F0 | 100.0% | Reimplemented From aa2f3c09dae5b3952fe4556c4f7f298407bebda2 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:06 +0200 Subject: [PATCH 030/299] reimplement: SHC_3BB0A8C1_0x00535200 100.00% Reimplemented --- .../filterUnitSelectionForUnitType.cpp | 20 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/filterUnitSelectionForUnitType.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/filterUnitSelectionForUnitType.cpp b/src/OpenSHC/Map/Units/UnitsState/filterUnitSelectionForUnitType.cpp new file mode 100644 index 000000000..fb57aefe9 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/filterUnitSelectionForUnitType.cpp @@ -0,0 +1,20 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + // FUNCTION: STRONGHOLDCRUSADER 0x00535200 + void UnitsState::filterUnitSelectionForUnitType(int unitType) + { + for (int unitID = 1; unitID < (int)this->maxUnitCount; ++unitID) { + if (this->units[unitID].isSelected != 0 && (short)this->units[unitID].unitType != unitType) { + this->units[unitID].isSelected = 0; + this->totalUnitsInSelection = this->totalUnitsInSelection - 1; + } + } + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 4d12b75cb..4d4002b94 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -50861,7 +50861,7 @@ SHC_3BB0A8C1_0x00535190 | 100.0% | Reimplemented SHC_3BB0A8C1_0x005351C0 | 0.0% | Pending -SHC_3BB0A8C1_0x00535200 | 0.0% | Pending +SHC_3BB0A8C1_0x00535200 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00535240 | 0.0% | Pending From 6868cb86911c85e62b75a598f2ff488e2a770435 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:07 +0200 Subject: [PATCH 031/299] reimplement: SHC_3BB0A8C1_0x005351C0 100.00% Reimplemented --- .../filterUnitSelectionExcludeUnitType.cpp | 20 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/filterUnitSelectionExcludeUnitType.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/filterUnitSelectionExcludeUnitType.cpp b/src/OpenSHC/Map/Units/UnitsState/filterUnitSelectionExcludeUnitType.cpp new file mode 100644 index 000000000..485ea5aaf --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/filterUnitSelectionExcludeUnitType.cpp @@ -0,0 +1,20 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + // FUNCTION: STRONGHOLDCRUSADER 0x005351C0 + void UnitsState::filterUnitSelectionExcludeUnitType(int unitType) + { + for (int unitID = 1; unitID < (int)this->maxUnitCount; ++unitID) { + if (this->units[unitID].isSelected != 0 && (short)this->units[unitID].unitType == unitType) { + this->units[unitID].isSelected = 0; + this->totalUnitsInSelection = this->totalUnitsInSelection - 1; + } + } + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 4d4002b94..047485e96 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -50859,7 +50859,7 @@ SHC_3BB0A8C1_0x00535150 | 0.0% | Pending SHC_3BB0A8C1_0x00535190 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x005351C0 | 0.0% | Pending +SHC_3BB0A8C1_0x005351C0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00535200 | 100.0% | Reimplemented From eea4ab9e4d26106a3df1e8b6e3daf77d413c4191 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:07 +0200 Subject: [PATCH 032/299] reimplement: SHC_3BB0A8C1_0x0053BB10 100.00% Reimplemented --- .../UnitsState/commitPendingUnitPosition.cpp | 21 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/commitPendingUnitPosition.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/commitPendingUnitPosition.cpp b/src/OpenSHC/Map/Units/UnitsState/commitPendingUnitPosition.cpp new file mode 100644 index 000000000..b28c6df0a --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/commitPendingUnitPosition.cpp @@ -0,0 +1,21 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + // FUNCTION: STRONGHOLDCRUSADER 0x0053BB10 + void UnitsState::commitPendingUnitPosition(int unitID) + { + if (this->units[unitID].field105_0xe8 != 0) { + this->units[unitID].tile = this->units[unitID].nextTileUnk; + this->units[unitID].x = this->units[unitID].mimicCurrentXPosition; + this->units[unitID].y = this->units[unitID].mimicCurrentYPosition; + } + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::setMoveDelayForUnitsOnSameTiles, this)( + unitID, this->units[unitID].tile); + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 047485e96..940e24f86 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -59653,7 +59653,7 @@ SHC_3BB0A8C1_0x0053B8B0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0053B8E0 | 0.0% | Pending -SHC_3BB0A8C1_0x0053BB10 | 0.0% | Pending +SHC_3BB0A8C1_0x0053BB10 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0053BB70 | 100.0% | Reimplemented From a5243a3d5184888af39743026da92c7cc5a2c652 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:07 +0200 Subject: [PATCH 033/299] reimplement: SHC_3BB0A8C1_0x0053E820 100.00% Reimplemented --- .../Units/UnitsState/commitUnitLocation.cpp | 21 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/commitUnitLocation.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/commitUnitLocation.cpp b/src/OpenSHC/Map/Units/UnitsState/commitUnitLocation.cpp new file mode 100644 index 000000000..a1aafc8c0 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/commitUnitLocation.cpp @@ -0,0 +1,21 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + // FUNCTION: STRONGHOLDCRUSADER 0x0053E820 + void UnitsState::commitUnitLocation(int unitID) + { + this->units[unitID].currentIndexInPathPlan = 0; + this->units[unitID].tunnelerFinishedDigging = 0; + this->units[unitID].field105_0xe8 = 0; + this->units[unitID].unknownMovementRelated_0x2d2 = 0; + this->units[unitID].movementRelated = 8; + this->units[unitID].unknownTestAgainst0_2 = 1; + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::setupUnitSharingCurrentTilePosition, this)(unitID); + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 940e24f86..c687c87fe 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -60091,7 +60091,7 @@ SHC_3BB0A8C1_0x0053E6C0 | 0.0% | Pending SHC_3BB0A8C1_0x0053E790 | 0.0% | Pending -SHC_3BB0A8C1_0x0053E820 | 0.0% | Pending +SHC_3BB0A8C1_0x0053E820 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0053E870 | 0.0% | Pending From c1befb42f0de5283d4753848d3b1f569a35564b0 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:08 +0200 Subject: [PATCH 034/299] reimplement: SHC_3BB0A8C1_0x00535810 100.00% Reimplemented --- .../selectionContainsOnlyArabAssassins.cpp | 26 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/selectionContainsOnlyArabAssassins.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/selectionContainsOnlyArabAssassins.cpp b/src/OpenSHC/Map/Units/UnitsState/selectionContainsOnlyArabAssassins.cpp new file mode 100644 index 000000000..4c36ccb20 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/selectionContainsOnlyArabAssassins.cpp @@ -0,0 +1,26 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x00535810 + BOOLEnum UnitsState::selectionContainsOnlyArabAssassins() + { + if (this->selectionArabAssassin == 0) { + return FALSE; + } + for (int i = 0; i <= 26; ++i) { + if (i != 22 && (&this->selectionEuropeanArchers)[i] != 0) { + return FALSE; + } + } + return TRUE; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index c687c87fe..bb5f3b422 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -51083,7 +51083,7 @@ SHC_3BB0A8C1_0x00535730 | 0.0% | Pending SHC_3BB0A8C1_0x005357E0 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x00535810 | 0.0% | Pending +SHC_3BB0A8C1_0x00535810 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00535840 | 100.0% | Reimplemented From a30dc49e55c719aa7f40e9655a2914e8c079048b Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:08 +0200 Subject: [PATCH 035/299] reimplement: SHC_3BB0A8C1_0x00535870 100.00% Reimplemented --- .../selectionHasShieldOrSiegeMobileUnits.cpp | 23 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/selectionHasShieldOrSiegeMobileUnits.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/selectionHasShieldOrSiegeMobileUnits.cpp b/src/OpenSHC/Map/Units/UnitsState/selectionHasShieldOrSiegeMobileUnits.cpp new file mode 100644 index 000000000..62573df62 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/selectionHasShieldOrSiegeMobileUnits.cpp @@ -0,0 +1,23 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + // FUNCTION: STRONGHOLDCRUSADER 0x00535870 + undefined4 UnitsState::selectionHasShieldOrSiegeMobileUnits() + { + if (this->selectionShield != 0 || this->selectionSiegeTower != 0 || this->selectionBatteringRam != 0) { + for (int i = 0; i <= 26; ++i) { + if (i != 15 && i != 13 && i != 14 && (&this->selectionEuropeanArchers)[i] != 0) { + return 0; + } + } + return 1; + } + return 0; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index bb5f3b422..b3af6b051 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -51087,7 +51087,7 @@ SHC_3BB0A8C1_0x00535810 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00535840 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x00535870 | 0.0% | Pending +SHC_3BB0A8C1_0x00535870 | 100.0% | Reimplemented SHC_3BB0A8C1_0x005358C0 | 100.0% | Reimplemented From d8b3c9215dff6c53f00639e82306b0a10f1e8b27 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:08 +0200 Subject: [PATCH 036/299] reimplement: SHC_3BB0A8C1_0x00535150 100.00% Reimplemented --- .../UnitsState/deselectAllUnitsOneByOne.cpp | 21 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/deselectAllUnitsOneByOne.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/deselectAllUnitsOneByOne.cpp b/src/OpenSHC/Map/Units/UnitsState/deselectAllUnitsOneByOne.cpp new file mode 100644 index 000000000..cceddfc70 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/deselectAllUnitsOneByOne.cpp @@ -0,0 +1,21 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" + +#include "OpenSHC/Globals/DAT_CurrentUnitSlotID.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + // FUNCTION: STRONGHOLDCRUSADER 0x00535150 + void UnitsState::deselectAllUnitsOneByOne() + { + for (DAT_CurrentUnitSlotID::instance = 1; (int)DAT_CurrentUnitSlotID::instance < (int)this->maxUnitCount; + DAT_CurrentUnitSlotID::instance = DAT_CurrentUnitSlotID::instance + 1) { + this->units[DAT_CurrentUnitSlotID::instance].isSelected = 0; + } + this->totalUnitsInSelection = 0; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index b3af6b051..306e5a14a 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -50855,7 +50855,7 @@ SHC_3BB0A8C1_0x00534F50 | 0.0% | Pending SHC_3BB0A8C1_0x005350B0 | 0.0% | Pending -SHC_3BB0A8C1_0x00535150 | 0.0% | Pending +SHC_3BB0A8C1_0x00535150 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00535190 | 100.0% | Reimplemented From 76ef3323e11ee4a49dbe36644f47911458d24079 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:09 +0200 Subject: [PATCH 037/299] reimplement: SHC_3BB0A8C1_0x00535520 100.00% Reimplemented --- .../selectionContainsEngineersOnly.cpp | 26 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/selectionContainsEngineersOnly.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/selectionContainsEngineersOnly.cpp b/src/OpenSHC/Map/Units/UnitsState/selectionContainsEngineersOnly.cpp new file mode 100644 index 000000000..40fbe9ff7 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/selectionContainsEngineersOnly.cpp @@ -0,0 +1,26 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x00535520 + BOOLEnum UnitsState::selectionContainsEngineersOnly() + { + if (this->selectionEngineers == 0) { + return FALSE; + } + for (int i = 0; i <= 26; ++i) { + if (i != 7 && (&this->selectionEuropeanArchers)[i] != 0) { + return FALSE; + } + } + return TRUE; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 306e5a14a..019053186 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -51065,7 +51065,7 @@ SHC_3BB0A8C1_0x00535513 | 0.0% | Pending SHC_3BB0A8C1_0x00535514 | 0.0% | Pending -SHC_3BB0A8C1_0x00535520 | 0.0% | Pending +SHC_3BB0A8C1_0x00535520 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00535550 | 100.0% | Reimplemented From 3579d7ce5aeb184aba94d0f3a0ea86e1aee1d960 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:09 +0200 Subject: [PATCH 038/299] reimplement: SHC_3BB0A8C1_0x00530080 100.00% Reimplemented --- .../isComputerManagedNonPeasant.cpp | 27 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/isComputerManagedNonPeasant.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/isComputerManagedNonPeasant.cpp b/src/OpenSHC/Map/Units/UnitsState/isComputerManagedNonPeasant.cpp new file mode 100644 index 000000000..c75dd8899 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/isComputerManagedNonPeasant.cpp @@ -0,0 +1,27 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Map/Units/UnitType.hpp" +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +#include "OpenSHC/Globals/DAT_UnitPropertiesDefinedData.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Map::Units::UnitType; + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x00530080 + BOOLEnum UnitsState::isComputerManagedNonPeasant(int unitID) + { + if (this->units[unitID].unitType == OpenSHC::Map::Units::UT_PEASANT) { + return FALSE; + } + return ( + BOOLEnum)(DAT_UnitPropertiesDefinedData::instance.COMPUTER_MANAGED[(short)this->units[unitID].unitType] + != 0); + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 019053186..6ae01ade5 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -49361,7 +49361,7 @@ SHC_3BB0A8C1_0x0052FE90 | 0.0% | Pending SHC_3BB0A8C1_0x0052FF80 | 0.0% | Pending -SHC_3BB0A8C1_0x00530080 | 0.0% | Pending +SHC_3BB0A8C1_0x00530080 | 100.0% | Reimplemented SHC_3BB0A8C1_0x005300B0 | 0.0% | Pending From 28a53239571308482f0c4eab29c5029be1b595b3 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:10 +0200 Subject: [PATCH 039/299] reimplement: SHC_3BB0A8C1_0x00537840 100.00% Reimplemented --- .../Map/Units/UnitsState/getRawDeerCount.cpp | 24 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/getRawDeerCount.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/getRawDeerCount.cpp b/src/OpenSHC/Map/Units/UnitsState/getRawDeerCount.cpp new file mode 100644 index 000000000..42b1bd263 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/getRawDeerCount.cpp @@ -0,0 +1,24 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Map/Units/UnitType.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Map::Units::UnitType; + + // FUNCTION: STRONGHOLDCRUSADER 0x00537840 + int UnitsState::getRawDeerCount() + { + int _deerCount = 0; + for (int unitID = 1; unitID < 2500; ++unitID) { + if (this->units[unitID].unitType == OpenSHC::Map::Units::UT_ANTELOPESHDEER) { + _deerCount = _deerCount + 1; + } + } + return _deerCount; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 6ae01ade5..0b6191b73 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -51239,7 +51239,7 @@ SHC_3BB0A8C1_0x00537700 | 0.0% | Pending SHC_3BB0A8C1_0x005377F0 | 0.0% | Pending -SHC_3BB0A8C1_0x00537840 | 0.0% | Pending +SHC_3BB0A8C1_0x00537840 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00537880 | 0.0% | Pending From 89a384d85e1483cae148ab82cb4876a658a00a00 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:10 +0200 Subject: [PATCH 040/299] reimplement: SHC_3BB0A8C1_0x005301F0 96.00% reg alloc differs --- .../countLivingNondyingUnitsForPlayer.cpp | 25 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/countLivingNondyingUnitsForPlayer.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/countLivingNondyingUnitsForPlayer.cpp b/src/OpenSHC/Map/Units/UnitsState/countLivingNondyingUnitsForPlayer.cpp new file mode 100644 index 000000000..92c41035d --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/countLivingNondyingUnitsForPlayer.cpp @@ -0,0 +1,25 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Map/Units/UnitLogicState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Map::Units::UnitLogicState; + + // FUNCTION: STRONGHOLDCRUSADER 0x005301F0 + int UnitsState::countLivingNondyingUnitsForPlayer(int playerID) + { + int _count = 0; + for (int unitID = 1; unitID < (int)this->maxUnitCount; ++unitID) { + if (this->units[unitID].logicalState == OpenSHC::Map::Units::ULS_NORMAL + && this->units[unitID].dying == 0 && this->units[unitID].owner == playerID) { + _count = _count + 1; + } + } + return _count; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 0b6191b73..483680c77 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -49365,7 +49365,7 @@ SHC_3BB0A8C1_0x00530080 | 100.0% | Reimplemented SHC_3BB0A8C1_0x005300B0 | 0.0% | Pending -SHC_3BB0A8C1_0x005301F0 | 0.0% | Pending +SHC_3BB0A8C1_0x005301F0 | 96.0% | reg alloc differs SHC_3BB0A8C1_0x00530210 | 0.0% | Pending From a4b90caea265ff253920d927388f55da98f0dcc0 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:10 +0200 Subject: [PATCH 041/299] reimplement: SHC_3BB0A8C1_0x0053E870 85.71% reg alloc differs --- .../UnitsState/resetUnitMovementState.cpp | 24 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/resetUnitMovementState.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/resetUnitMovementState.cpp b/src/OpenSHC/Map/Units/UnitsState/resetUnitMovementState.cpp new file mode 100644 index 000000000..70a9bbfa4 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/resetUnitMovementState.cpp @@ -0,0 +1,24 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + // FUNCTION: STRONGHOLDCRUSADER 0x0053E870 + void UnitsState::resetUnitMovementState(int unitID) + { + short _wasPositionPending = this->units[unitID].unknownTestAgainst0_2; + this->units[unitID].currentIndexInPathPlan = 0; + this->units[unitID].tunnelerFinishedDigging = 0; + this->units[unitID].movementRelated = 8; + this->units[unitID].unknownTestAgainst0_2 = 0; + this->units[unitID].field105_0xe8 = 0; + this->units[unitID].unknownMovementRelated_0x2d2 = 0; + if (_wasPositionPending != 0) { + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::commitPendingUnitPosition, this)(unitID); + } + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 483680c77..019f1d6a4 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -60093,7 +60093,7 @@ SHC_3BB0A8C1_0x0053E790 | 0.0% | Pending SHC_3BB0A8C1_0x0053E820 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x0053E870 | 0.0% | Pending +SHC_3BB0A8C1_0x0053E870 | 85.7% | reg alloc differs SHC_3BB0A8C1_0x0053E8D0 | 100.0% | Reimplemented From aa644caa5c72b0cf281827122969488c84d5cec3 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:11 +0200 Subject: [PATCH 042/299] reimplement: SHC_3BB0A8C1_0x0053A560 100.00% Reimplemented --- .../UnitsState/getLivingSelectableUnit.cpp | 25 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/getLivingSelectableUnit.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/getLivingSelectableUnit.cpp b/src/OpenSHC/Map/Units/UnitsState/getLivingSelectableUnit.cpp new file mode 100644 index 000000000..9a018eac7 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/getLivingSelectableUnit.cpp @@ -0,0 +1,25 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Map/Units/UnitLogicState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Map::Units::UnitLogicState; + + // FUNCTION: STRONGHOLDCRUSADER 0x0053A560 + int UnitsState::getLivingSelectableUnit(int playerID) + { + for (int unitID = 1; unitID < (int)this->maxUnitCount; ++unitID) { + if (this->units[unitID].owner == playerID + && this->units[unitID].logicalState == OpenSHC::Map::Units::ULS_NORMAL + && this->units[unitID].dying == 0 && this->units[unitID].isSelectable_OR_matchTime != 0) { + return unitID; + } + } + return 0; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 019f1d6a4..ce82d6382 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -59615,7 +59615,7 @@ SHC_3BB0A8C1_0x0053A4C1 | 0.0% | Pending SHC_3BB0A8C1_0x0053A4D0 | 0.0% | Pending -SHC_3BB0A8C1_0x0053A560 | 0.0% | Pending +SHC_3BB0A8C1_0x0053A560 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0053A5B0 | 0.0% | Pending From a19b886e6b4420d1f32a9a3a75d8d9ee43dd5c6d Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:11 +0200 Subject: [PATCH 043/299] reimplement: SHC_3BB0A8C1_0x00535910 100.00% Reimplemented --- .../UnitsState/selectionHasNoRangedUnits.cpp | 21 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/selectionHasNoRangedUnits.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/selectionHasNoRangedUnits.cpp b/src/OpenSHC/Map/Units/UnitsState/selectionHasNoRangedUnits.cpp new file mode 100644 index 000000000..1a312a10f --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/selectionHasNoRangedUnits.cpp @@ -0,0 +1,21 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + // FUNCTION: STRONGHOLDCRUSADER 0x00535910 + undefined4 UnitsState::selectionHasNoRangedUnits() + { + if (this->selectionEuropeanArchers == 0 && this->selectionCrossbowmen == 0 && this->selectionArabArcher == 0 + && this->selectionArabSlinger == 0 && this->selectionCatapults == 0 && this->selectionTrebuchets == 0 + && this->selectionArabHorseArchers == 0 && this->selectionArabFireThrower == 0 + && this->selectionFireBallista == 0 && this->selectionMangonel == 0 && this->selectionBallista == 0) { + return 1; + } + return 0; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index ce82d6382..76815dd3b 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -51091,7 +51091,7 @@ SHC_3BB0A8C1_0x00535870 | 100.0% | Reimplemented SHC_3BB0A8C1_0x005358C0 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x00535910 | 0.0% | Pending +SHC_3BB0A8C1_0x00535910 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00535980 | 100.0% | Reimplemented From ad830e7003582d73a3945cbb6f45864a42cedd1e Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:11 +0200 Subject: [PATCH 044/299] reimplement: SHC_3BB0A8C1_0x005369F0 80.00% switch shape differs --- .../selectionHasUnmannedSiegeEngine.cpp | 29 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/selectionHasUnmannedSiegeEngine.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/selectionHasUnmannedSiegeEngine.cpp b/src/OpenSHC/Map/Units/UnitsState/selectionHasUnmannedSiegeEngine.cpp new file mode 100644 index 000000000..1b91db858 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/selectionHasUnmannedSiegeEngine.cpp @@ -0,0 +1,29 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x005369F0 + BOOLEnum UnitsState::selectionHasUnmannedSiegeEngine(int unitID) + { + if (this->units[unitID].digTileX__OR__countCurrentlyManningEnginers__OR__forCowsRandomBelow300 != 0) { + return FALSE; + } + switch (this->units[unitID].unitType) { + case OpenSHC::Map::Units::UT_S_CATAPULT: + case OpenSHC::Map::Units::UT_S_TREBUCHET: + case OpenSHC::Map::Units::UT_S_TOWER: + case OpenSHC::Map::Units::UT_S_BATTERINGRAM: + case OpenSHC::Map::Units::UT_S_SHIELD: + return (BOOLEnum)(this->selectionEngineers != 0); + } + return FALSE; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 76815dd3b..f67cd817c 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -51151,7 +51151,7 @@ SHC_3BB0A8C1_0x005368D0 | 0.0% | Pending SHC_3BB0A8C1_0x00536970 | 0.0% | Pending -SHC_3BB0A8C1_0x005369F0 | 0.0% | Pending +SHC_3BB0A8C1_0x005369F0 | 80.0% | switch shape differs SHC_3BB0A8C1_0x00536A34 | 0.0% | Pending From b361cc8e96bf11c639bdee620690c3f5eed96b00 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:12 +0200 Subject: [PATCH 045/299] reimplement: SHC_3BB0A8C1_0x00536C70 100.00% Reimplemented --- .../Units/UnitsState/queueEscapeCommand.cpp | 23 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/queueEscapeCommand.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/queueEscapeCommand.cpp b/src/OpenSHC/Map/Units/UnitsState/queueEscapeCommand.cpp new file mode 100644 index 000000000..eb56c0fe0 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/queueEscapeCommand.cpp @@ -0,0 +1,23 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Synchrony/GameSynchronyState.func.hpp" +#include "OpenSHC/Commands/GameCommandType.hpp" + +#include "OpenSHC/Globals/DAT_GameSynchronyState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Commands::GameCommandType; + + // FUNCTION: STRONGHOLDCRUSADER 0x00536C70 + void UnitsState::queueEscapeCommand() + { + DAT_GameSynchronyState::instance.DAT_GameCommandParam0 = 0; + MACRO_CALL_MEMBER(OpenSHC::Synchrony::GameSynchronyState_Func::queueCommand, DAT_GameSynchronyState::ptr)( + OpenSHC::Commands::GCT_ESCAPE); + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index f67cd817c..fa237e622 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -51203,7 +51203,7 @@ SHC_3BB0A8C1_0x00536A51 | 0.0% | Pending SHC_3BB0A8C1_0x00536A60 | 0.0% | Pending -SHC_3BB0A8C1_0x00536C70 | 0.0% | Pending +SHC_3BB0A8C1_0x00536C70 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00536C90 | 0.0% | Pending From 6a07a017c55080b224f0d1f7e9c4b3b465404072 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:12 +0200 Subject: [PATCH 046/299] reimplement: SHC_3BB0A8C1_0x00537070 86.36% enum cast, reg alloc --- .../giveTribeMoveInstructionHumans.cpp | 25 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/giveTribeMoveInstructionHumans.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/giveTribeMoveInstructionHumans.cpp b/src/OpenSHC/Map/Units/UnitsState/giveTribeMoveInstructionHumans.cpp new file mode 100644 index 000000000..4195e5725 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/giveTribeMoveInstructionHumans.cpp @@ -0,0 +1,25 @@ +#include "OpenSHC/Map/Units/TribesState.func.hpp" +#include "OpenSHC/Map/Units/UnitsState.func.hpp" + +#include "OpenSHC/Globals/DAT_TribesState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + // FUNCTION: STRONGHOLDCRUSADER 0x00537070 + void UnitsState::giveTribeMoveInstructionHumans( + int tribeID, uint x, uint y, int rallyBool, MatchSpeedInstructionEnum speedMatching) + { + DAT_TribesState::instance.tribes[tribeID].freeUnitSpeeds = 0; + if ((char)speedMatching < 0) { + speedMatching = (Instructions::MatchSpeedInstructionEnum)(speedMatching & 0xffffff7f); + DAT_TribesState::instance.tribes[tribeID].freeUnitSpeeds = 1; + } + MACRO_CALL_MEMBER(OpenSHC::Map::Units::TribesState_Func::giveTribeMoveInstruction, DAT_TribesState::ptr)( + tribeID, x, y, rallyBool, 1, (UnitMatchSpeedEnum)speedMatching); + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index fa237e622..efb61a3e5 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -51219,7 +51219,7 @@ SHC_3BB0A8C1_0x00536E10 | 0.0% | Pending SHC_3BB0A8C1_0x00536E30 | 0.0% | Pending -SHC_3BB0A8C1_0x00537070 | 0.0% | Pending +SHC_3BB0A8C1_0x00537070 | 86.4% | enum cast, reg alloc SHC_3BB0A8C1_0x005370C0 | 0.0% | Pending From 49e37260aa4b511d984cf53d12c79f22e3ad58d7 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:13 +0200 Subject: [PATCH 047/299] reimplement: SHC_3BB0A8C1_0x005340F0 100.00% Reimplemented --- ...MapOrientationCorrectedFacingDirection.cpp | 23 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/adjustUnitMapOrientationRelatedPositionBasedOnMapOrientationCorrectedFacingDirection.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/adjustUnitMapOrientationRelatedPositionBasedOnMapOrientationCorrectedFacingDirection.cpp b/src/OpenSHC/Map/Units/UnitsState/adjustUnitMapOrientationRelatedPositionBasedOnMapOrientationCorrectedFacingDirection.cpp new file mode 100644 index 000000000..c914148b1 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/adjustUnitMapOrientationRelatedPositionBasedOnMapOrientationCorrectedFacingDirection.cpp @@ -0,0 +1,23 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" + +#include "OpenSHC/Globals/DAT_UnitPropertiesDefinedData.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + // FUNCTION: STRONGHOLDCRUSADER 0x005340F0 + void UnitsState::adjustUnitMapOrientationRelatedPositionBasedOnMapOrientationCorrectedFacingDirection( + int unitID) + { + this->units[unitID].orientationRelatedPositionX = this->units[unitID].orientationRelatedPositionX + + (short)DAT_UnitPropertiesDefinedData::instance + .UnitOrientationRelatedOffset[this->units[unitID].facingDirectionMapOrientationCorrected][0]; + this->units[unitID].orientationRelatedPositionY = this->units[unitID].orientationRelatedPositionY + + (short)DAT_UnitPropertiesDefinedData::instance + .UnitOrientationRelatedOffset[this->units[unitID].facingDirectionMapOrientationCorrected][1]; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index efb61a3e5..0370fc171 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -50797,7 +50797,7 @@ SHC_3BB0A8C1_0x005340E0 | 0.0% | Pending SHC_3BB0A8C1_0x005340E4 | 0.0% | Pending -SHC_3BB0A8C1_0x005340F0 | 0.0% | Pending +SHC_3BB0A8C1_0x005340F0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00534130 | 0.0% | Pending From 619026bdd2d262d93333def0aabc637949a5bd10 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:13 +0200 Subject: [PATCH 048/299] reimplement: SHC_3BB0A8C1_0x00536190 72.41% incr scheduled before call --- .../UnitsState/selectTribeUnitsForPlayer.cpp | 23 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/selectTribeUnitsForPlayer.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/selectTribeUnitsForPlayer.cpp b/src/OpenSHC/Map/Units/UnitsState/selectTribeUnitsForPlayer.cpp new file mode 100644 index 000000000..6a763dc85 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/selectTribeUnitsForPlayer.cpp @@ -0,0 +1,23 @@ +#include "OpenSHC/Map/Units/TribesState.func.hpp" +#include "OpenSHC/Map/Units/UnitsState.func.hpp" + +#include "OpenSHC/Globals/DAT_TribesState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + // FUNCTION: STRONGHOLDCRUSADER 0x00536190 + void UnitsState::selectTribeUnitsForPlayer(int playerID, int tribeID) + { + for (int indexInTribe = 0; indexInTribe < DAT_TribesState::instance.tribes[tribeID].size; ++indexInTribe) { + int unitID = MACRO_CALL_MEMBER(OpenSHC::Map::Units::TribesState_Func::getUnitIDForIndexInTribe, + DAT_TribesState::ptr)(tribeID, indexInTribe); + this->units[unitID].ifSelectedThenPlayerID = (short)playerID; + this->unitCountOfSelection[playerID] = this->unitCountOfSelection[playerID] + 1; + } + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 0370fc171..43254466a 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -51111,7 +51111,7 @@ SHC_3BB0A8C1_0x00535FD0 | 0.0% | Pending SHC_3BB0A8C1_0x005360A0 | 0.0% | Pending -SHC_3BB0A8C1_0x00536190 | 0.0% | Pending +SHC_3BB0A8C1_0x00536190 | 72.4% | incr scheduled before call SHC_3BB0A8C1_0x005361F0 | 0.0% | Pending From 360e7cf3098b1e4f5cc6fd2e5ce9f805934f0f59 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:13 +0200 Subject: [PATCH 049/299] reimplement: SHC_3BB0A8C1_0x005377F0 100.00% Reimplemented --- .../UnitsState/getAliveLordForPlayer.cpp | 28 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/getAliveLordForPlayer.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/getAliveLordForPlayer.cpp b/src/OpenSHC/Map/Units/UnitsState/getAliveLordForPlayer.cpp new file mode 100644 index 000000000..867ecbf36 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/getAliveLordForPlayer.cpp @@ -0,0 +1,28 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Map/Units/UnitLogicState.hpp" +#include "OpenSHC/Map/Units/UnitType.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Map::Units::UnitLogicState; + using OpenSHC::Map::Units::UnitType; + + // FUNCTION: STRONGHOLDCRUSADER 0x005377F0 + int UnitsState::getAliveLordForPlayer(int playerID) + { + for (int unitID = 1; unitID < (int)this->maxUnitCount; ++unitID) { + if (this->units[unitID].unitType == OpenSHC::Map::Units::UT_LORD + && this->units[unitID].owner == playerID + && this->units[unitID].logicalState == OpenSHC::Map::Units::ULS_NORMAL + && this->units[unitID].dying == 0) { + return unitID; + } + } + return 0; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 43254466a..5b130cad9 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -51237,7 +51237,7 @@ SHC_3BB0A8C1_0x005371F0 | 0.0% | Pending SHC_3BB0A8C1_0x00537700 | 0.0% | Pending -SHC_3BB0A8C1_0x005377F0 | 0.0% | Pending +SHC_3BB0A8C1_0x005377F0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00537840 | 100.0% | Reimplemented From 8a99771cbc802fc750a75fe5e1fedcf70424a951 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:14 +0200 Subject: [PATCH 050/299] reimplement: SHC_3BB0A8C1_0x00534380 77.61% orig walks matrix row ptr --- .../isWorkplaceBuildingOnAdjacentTile.cpp | 28 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/isWorkplaceBuildingOnAdjacentTile.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/isWorkplaceBuildingOnAdjacentTile.cpp b/src/OpenSHC/Map/Units/UnitsState/isWorkplaceBuildingOnAdjacentTile.cpp new file mode 100644 index 000000000..6c5f22a4b --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/isWorkplaceBuildingOnAdjacentTile.cpp @@ -0,0 +1,28 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" + +#include "OpenSHC/Globals/DAT_TileMapState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + // FUNCTION: STRONGHOLDCRUSADER 0x00534380 + undefined4 UnitsState::isWorkplaceBuildingOnAdjacentTile(int unitID) + { + if (this->units[unitID].workplaceBuildingID_1 == 0) { + return 0; + } + for (int direction = 0; direction < 8; ++direction) { + if (DAT_TileMapState::instance.BuildingLayer + [DAT_TileMapState::instance.directionTranslationMatrix[this->units[unitID].y][direction] + + this->units[unitID].tile] + == this->units[unitID].workplaceBuildingID_1) { + return 1; + } + } + return 0; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 5b130cad9..c5e4785d2 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -50803,7 +50803,7 @@ SHC_3BB0A8C1_0x00534130 | 0.0% | Pending SHC_3BB0A8C1_0x00534240 | 0.0% | Pending -SHC_3BB0A8C1_0x00534380 | 0.0% | Pending +SHC_3BB0A8C1_0x00534380 | 77.6% | orig walks matrix row ptr SHC_3BB0A8C1_0x005343C0 | 0.0% | Pending From 21bc4ebaf470edea7b39916edf2dd393a9a0e928 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:14 +0200 Subject: [PATCH 051/299] reimplement: SHC_3BB0A8C1_0x00536DE0 100.00% Reimplemented --- .../clearSelectionCountsAndPlayerIDs.cpp | 28 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/clearSelectionCountsAndPlayerIDs.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/clearSelectionCountsAndPlayerIDs.cpp b/src/OpenSHC/Map/Units/UnitsState/clearSelectionCountsAndPlayerIDs.cpp new file mode 100644 index 000000000..b32ee3eb3 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/clearSelectionCountsAndPlayerIDs.cpp @@ -0,0 +1,28 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" + +#include "OpenSHC/Globals/DAT_CurrentUnitSlotID.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + // FUNCTION: STRONGHOLDCRUSADER 0x00536DE0 + void UnitsState::clearSelectionCountsAndPlayerIDs() + { + this->unitCountOfSelection[1] = 0; + this->unitCountOfSelection[2] = 0; + this->unitCountOfSelection[3] = 0; + this->unitCountOfSelection[4] = 0; + this->unitCountOfSelection[5] = 0; + this->unitCountOfSelection[6] = 0; + this->unitCountOfSelection[7] = 0; + this->unitCountOfSelection[8] = 0; + for (DAT_CurrentUnitSlotID::instance = 1; (int)DAT_CurrentUnitSlotID::instance < (int)this->maxUnitCount; + DAT_CurrentUnitSlotID::instance = DAT_CurrentUnitSlotID::instance + 1) { + this->units[DAT_CurrentUnitSlotID::instance].ifSelectedThenPlayerID = 0; + } + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index c5e4785d2..a65542e98 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -51213,7 +51213,7 @@ SHC_3BB0A8C1_0x00536CF0 | 0.0% | Pending SHC_3BB0A8C1_0x00536DA0 | 0.0% | Pending -SHC_3BB0A8C1_0x00536DE0 | 0.0% | Pending +SHC_3BB0A8C1_0x00536DE0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00536E10 | 0.0% | Pending From 572a203d53fbdcb678a2c7e246d2011a893cbbf8 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:15 +0200 Subject: [PATCH 052/299] reimplement: SHC_3BB0A8C1_0x0052FCA0 100.00% Reimplemented --- .../setFacingDirectionTowardCoords.cpp | 26 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/setFacingDirectionTowardCoords.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/setFacingDirectionTowardCoords.cpp b/src/OpenSHC/Map/Units/UnitsState/setFacingDirectionTowardCoords.cpp new file mode 100644 index 000000000..ab28ac652 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/setFacingDirectionTowardCoords.cpp @@ -0,0 +1,26 @@ +#include "OpenSHC/Map/Navigation/DirectionAlgorithmState.func.hpp" +#include "OpenSHC/Map/Units/UnitsState.func.hpp" + +#include "OpenSHC/Globals/DAT_DirectionAlgorithmState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + // FUNCTION: STRONGHOLDCRUSADER 0x0052FCA0 + void UnitsState::setFacingDirectionTowardCoords(int unitID, int x, int y) + { + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::DirectionAlgorithmState_Func::calculateOrientation, + DAT_DirectionAlgorithmState::ptr)(this->units[unitID].x, this->units[unitID].y, x, y); + if (DAT_DirectionAlgorithmState::instance.orientation == 15) { + return; + } + if (this->units[unitID].facingDirection == DAT_DirectionAlgorithmState::instance.orientation) { + return; + } + this->units[unitID].facingDirection = (short)DAT_DirectionAlgorithmState::instance.orientation; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index a65542e98..ec17b917c 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -49351,7 +49351,7 @@ SHC_3BB0A8C1_0x0052FBF0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0052FC30 | 0.0% | Pending -SHC_3BB0A8C1_0x0052FCA0 | 0.0% | Pending +SHC_3BB0A8C1_0x0052FCA0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0052FD00 | 0.0% | Pending From 1a3f476945ed417c0441bf7d809ccd1e42248bae Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:15 +0200 Subject: [PATCH 053/299] reimplement: SHC_3BB0A8C1_0x005302B0 100.00% Reimplemented --- .../Units/UnitsState/killAllUnownedUnits.cpp | 28 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/killAllUnownedUnits.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/killAllUnownedUnits.cpp b/src/OpenSHC/Map/Units/UnitsState/killAllUnownedUnits.cpp new file mode 100644 index 000000000..cadce6bfd --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/killAllUnownedUnits.cpp @@ -0,0 +1,28 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Map/Units/States/UnitState.hpp" +#include "OpenSHC/Map/Units/UnitLogicState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Map::Units::UnitLogicState; + using OpenSHC::Map::Units::States::UnitState; + + // FUNCTION: STRONGHOLDCRUSADER 0x005302B0 + void UnitsState::killAllUnownedUnits() + { + for (int unitID = 1; unitID < (int)this->maxUnitCount; ++unitID) { + if (this->units[unitID].logicalState == OpenSHC::Map::Units::ULS_NORMAL + && this->units[unitID].dying == 0 && this->units[unitID].owner == 0 + && this->units[unitID].isStalked != 0) { + this->units[unitID].state.generic = OpenSHC::Map::Units::States::US_STONE_DEATH_01; + this->units[unitID].animationCycleNumber = 0; + this->units[unitID].dying = 1; + } + } + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index ec17b917c..2ffdd869b 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -49371,7 +49371,7 @@ SHC_3BB0A8C1_0x00530210 | 0.0% | Pending SHC_3BB0A8C1_0x00530240 | 0.0% | Pending -SHC_3BB0A8C1_0x005302B0 | 0.0% | Pending +SHC_3BB0A8C1_0x005302B0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00530310 | 0.0% | Pending From 937b77bf5d80f79f56919ef51f297ff1d222adc8 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:15 +0200 Subject: [PATCH 054/299] reimplement: SHC_3BB0A8C1_0x00536CC0 100.00% Reimplemented --- .../queueClickNavigateMenuOrEscape.cpp | 24 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/queueClickNavigateMenuOrEscape.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/queueClickNavigateMenuOrEscape.cpp b/src/OpenSHC/Map/Units/UnitsState/queueClickNavigateMenuOrEscape.cpp new file mode 100644 index 000000000..98c159d54 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/queueClickNavigateMenuOrEscape.cpp @@ -0,0 +1,24 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Synchrony/GameSynchronyState.func.hpp" +#include "OpenSHC/Commands/GameCommandType.hpp" + +#include "OpenSHC/Globals/DAT_GameSynchronyState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Commands::GameCommandType; + + // FUNCTION: STRONGHOLDCRUSADER 0x00536CC0 + void UnitsState::queueClickNavigateMenuOrEscape(undefined4 param_1) + { + DAT_GameSynchronyState::instance.DAT_GameCommandParam0 = 0xfffffffe; + DAT_GameSynchronyState::instance.DAT_GameCommandParam1 = param_1; + MACRO_CALL_MEMBER(OpenSHC::Synchrony::GameSynchronyState_Func::queueCommand, DAT_GameSynchronyState::ptr)( + OpenSHC::Commands::GCT_ESCAPE); + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 2ffdd869b..c86b00065 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -51207,7 +51207,7 @@ SHC_3BB0A8C1_0x00536C70 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00536C90 | 0.0% | Pending -SHC_3BB0A8C1_0x00536CC0 | 0.0% | Pending +SHC_3BB0A8C1_0x00536CC0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00536CF0 | 0.0% | Pending From d41d112198c8588e1962474d45eeef3e2f4fc7ab Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:16 +0200 Subject: [PATCH 055/299] reimplement: SHC_3BB0A8C1_0x00530390 100.00% Reimplemented --- .../Map/Units/UnitsState/killUnits.cpp | 29 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/killUnits.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/killUnits.cpp b/src/OpenSHC/Map/Units/UnitsState/killUnits.cpp new file mode 100644 index 000000000..8202963fc --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/killUnits.cpp @@ -0,0 +1,29 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Map/Units/States/UnitState.hpp" +#include "OpenSHC/Map/Units/UnitLogicState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Map::Units::UnitLogicState; + using OpenSHC::Map::Units::States::UnitState; + + // FUNCTION: STRONGHOLDCRUSADER 0x00530390 + void UnitsState::killUnits(int playerID) + { + for (int unitID = 1; unitID < (int)this->maxUnitCount; ++unitID) { + if (this->units[unitID].logicalState == OpenSHC::Map::Units::ULS_NORMAL + && this->units[unitID].dying == 0 && this->units[unitID].isStalked == 0 + && this->units[unitID].owner == playerID) { + this->units[unitID].state.generic = OpenSHC::Map::Units::States::US_STONE_DEATH_01; + this->units[unitID].animationCycleNumber = 0; + this->units[unitID].dying = 1; + this->units[unitID].killedFlagUnk = 1; + } + } + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index c86b00065..964efef00 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -49375,7 +49375,7 @@ SHC_3BB0A8C1_0x005302B0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00530310 | 0.0% | Pending -SHC_3BB0A8C1_0x00530390 | 0.0% | Pending +SHC_3BB0A8C1_0x00530390 | 100.0% | Reimplemented SHC_3BB0A8C1_0x005303B0 | 0.0% | Pending From 0aa4598717b9273e9328a90b80028ad561b36882 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:16 +0200 Subject: [PATCH 056/299] reimplement: SHC_3BB0A8C1_0x0052FC30 100.00% Reimplemented --- .../setFacingDirectionTowardUnit.cpp | 27 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/setFacingDirectionTowardUnit.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/setFacingDirectionTowardUnit.cpp b/src/OpenSHC/Map/Units/UnitsState/setFacingDirectionTowardUnit.cpp new file mode 100644 index 000000000..5407cd49a --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/setFacingDirectionTowardUnit.cpp @@ -0,0 +1,27 @@ +#include "OpenSHC/Map/Navigation/DirectionAlgorithmState.func.hpp" +#include "OpenSHC/Map/Units/UnitsState.func.hpp" + +#include "OpenSHC/Globals/DAT_DirectionAlgorithmState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + // FUNCTION: STRONGHOLDCRUSADER 0x0052FC30 + void UnitsState::setFacingDirectionTowardUnit(int unitID, int targetUnitID) + { + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::DirectionAlgorithmState_Func::calculateOrientation, + DAT_DirectionAlgorithmState::ptr)( + this->units[unitID].x, this->units[unitID].y, this->units[targetUnitID].x, this->units[targetUnitID].y); + if (DAT_DirectionAlgorithmState::instance.orientation == 15) { + return; + } + if (this->units[unitID].facingDirection == DAT_DirectionAlgorithmState::instance.orientation) { + return; + } + this->units[unitID].facingDirection = (short)DAT_DirectionAlgorithmState::instance.orientation; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 964efef00..1e0e16513 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -49349,7 +49349,7 @@ SHC_3BB0A8C1_0x0052FBB0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0052FBF0 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x0052FC30 | 0.0% | Pending +SHC_3BB0A8C1_0x0052FC30 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0052FCA0 | 100.0% | Reimplemented From 0e15c8d8f5fcc16198c2bc03404bfb8cac08207a Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:17 +0200 Subject: [PATCH 057/299] reimplement: SHC_3BB0A8C1_0x00537100 100.00% Reimplemented --- .../queueDisbandAndAttackCommand2Params.cpp | 24 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/queueDisbandAndAttackCommand2Params.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/queueDisbandAndAttackCommand2Params.cpp b/src/OpenSHC/Map/Units/UnitsState/queueDisbandAndAttackCommand2Params.cpp new file mode 100644 index 000000000..83cf8e590 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/queueDisbandAndAttackCommand2Params.cpp @@ -0,0 +1,24 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Synchrony/GameSynchronyState.func.hpp" +#include "OpenSHC/Commands/GameCommandType.hpp" + +#include "OpenSHC/Globals/DAT_GameSynchronyState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Commands::GameCommandType; + + // FUNCTION: STRONGHOLDCRUSADER 0x00537100 + void UnitsState::queueDisbandAndAttackCommand2Params(undefined4 param_1, undefined4 param_2) + { + DAT_GameSynchronyState::instance.DAT_GameCommandParam0 = param_1; + DAT_GameSynchronyState::instance.DAT_GameCommandParam1 = param_2; + MACRO_CALL_MEMBER(OpenSHC::Synchrony::GameSynchronyState_Func::queueCommand, DAT_GameSynchronyState::ptr)( + OpenSHC::Commands::GCT_DISBAND_AND_ATTACK_UNITS); + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 1e0e16513..58cdc14ae 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -51223,7 +51223,7 @@ SHC_3BB0A8C1_0x00537070 | 86.4% | enum cast, reg alloc SHC_3BB0A8C1_0x005370C0 | 0.0% | Pending -SHC_3BB0A8C1_0x00537100 | 0.0% | Pending +SHC_3BB0A8C1_0x00537100 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00537130 | 0.0% | Pending From 8e27838a7102b480441ac05111709f12a2de27b4 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:17 +0200 Subject: [PATCH 058/299] reimplement: SHC_3BB0A8C1_0x005355E0 100.00% Reimplemented --- .../selectionHasMixedAssaultAndInfantry.cpp | 27 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/selectionHasMixedAssaultAndInfantry.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/selectionHasMixedAssaultAndInfantry.cpp b/src/OpenSHC/Map/Units/UnitsState/selectionHasMixedAssaultAndInfantry.cpp new file mode 100644 index 000000000..43fc774de --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/selectionHasMixedAssaultAndInfantry.cpp @@ -0,0 +1,27 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + // FUNCTION: STRONGHOLDCRUSADER 0x005355E0 + undefined4 UnitsState::selectionHasMixedAssaultAndInfantry() + { + if (this->selectionKnights != 0 || this->selectionLaddermen != 0 || this->selectionBatteringRam != 0 + || this->selectionTrebuchets != 0 || this->selectionCatapults != 0 + || this->selectionArabHorseArchers != 0 || this->selectionFireBallista != 0 + || this->selectionSiegeTower != 0) { + for (int i = 0; i <= 26; ++i) { + if (i != 6 && i != 8 && i != 13 && i != 12 && i != 11 && i != 23 && i != 26 && i != 14 + && (&this->selectionEuropeanArchers)[i] != 0) { + return 0; + } + } + return 1; + } + return 0; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 58cdc14ae..48c2ce025 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -51073,7 +51073,7 @@ SHC_3BB0A8C1_0x00535560 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00535580 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x005355E0 | 0.0% | Pending +SHC_3BB0A8C1_0x005355E0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00535680 | 0.0% | Pending From bac87edea2bcd1c3b04d084419778b4e0cf667d4 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:17 +0200 Subject: [PATCH 059/299] reimplement: SHC_3BB0A8C1_0x0052F4E0 100.00% Reimplemented --- .../isUnitRegisteredOnItsOwnTile.cpp | 37 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/isUnitRegisteredOnItsOwnTile.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/isUnitRegisteredOnItsOwnTile.cpp b/src/OpenSHC/Map/Units/UnitsState/isUnitRegisteredOnItsOwnTile.cpp new file mode 100644 index 000000000..576137bf5 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/isUnitRegisteredOnItsOwnTile.cpp @@ -0,0 +1,37 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Map/Units/UnitLogicState.hpp" + +#include "OpenSHC/Globals/DAT_TileMapState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Map::Units::UnitLogicState; + + // FUNCTION: STRONGHOLDCRUSADER 0x0052F4E0 + undefined4 UnitsState::isUnitRegisteredOnItsOwnTile(int unitID) + { + int _tile = this->units[unitID].tile; + int _otherUnitID = (short)DAT_TileMapState::instance.UnitLayer[_tile]; + if (this->units[unitID].logicalState != OpenSHC::Map::Units::ULS_NORMAL) { + return 1; + } + if (this->units[unitID].unknownTestAgainst0_2 != 0) { + return 1; + } + if (_tile == 0) { + return 0; + } + while (_otherUnitID != 0) { + if (_otherUnitID == unitID) { + return 1; + } + _otherUnitID = (short)this->units[_otherUnitID].nextUnitOnTheSameTile; + } + return 0; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 48c2ce025..d2f11f5d9 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -49329,7 +49329,7 @@ SHC_3BB0A8C1_0x0052F440 | 0.0% | Pending SHC_3BB0A8C1_0x0052F4A0 | 0.0% | Pending -SHC_3BB0A8C1_0x0052F4E0 | 0.0% | Pending +SHC_3BB0A8C1_0x0052F4E0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0052F550 | 0.0% | Pending From e438c73c0f1e77cb6f001a34041cb5db44f4b874 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:18 +0200 Subject: [PATCH 060/299] reimplement: SHC_3BB0A8C1_0x00535DF0 46.15% call+reg alloc differs --- .../UnitsState/getFirstSelectedUnitID.cpp | 25 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/getFirstSelectedUnitID.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/getFirstSelectedUnitID.cpp b/src/OpenSHC/Map/Units/UnitsState/getFirstSelectedUnitID.cpp new file mode 100644 index 000000000..ee8a483c0 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/getFirstSelectedUnitID.cpp @@ -0,0 +1,25 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Synchrony/GameSynchronyState.func.hpp" +#include "OpenSHC/Commands/GameCommandType.hpp" + +#include "OpenSHC/Globals/DAT_GameSynchronyState.hpp" +#include "OpenSHC/Globals/DAT_TribesState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Commands::GameCommandType; + + // FUNCTION: STRONGHOLDCRUSADER 0x00535DF0 + void UnitsState::getFirstSelectedUnitID(undefined4 param_1) + { + DAT_GameSynchronyState::instance.DAT_GameCommandParam1 = DAT_TribesState::instance.DAT_CurrentTribeID; + DAT_GameSynchronyState::instance.DAT_GameCommandParam0 = param_1; + MACRO_CALL_MEMBER(OpenSHC::Synchrony::GameSynchronyState_Func::queueCommand, DAT_GameSynchronyState::ptr)( + (GameCommandType)0x48); + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index d2f11f5d9..20ffd67ce 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -51103,7 +51103,7 @@ SHC_3BB0A8C1_0x00535B00 | 0.0% | Pending SHC_3BB0A8C1_0x00535BC0 | 0.0% | Pending -SHC_3BB0A8C1_0x00535DF0 | 0.0% | Pending +SHC_3BB0A8C1_0x00535DF0 | 46.1% | call+reg alloc differs SHC_3BB0A8C1_0x00535E20 | 0.0% | Pending From 2f87f1eb41aba2fae0609b07e4bdbf5327ed94db Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:18 +0200 Subject: [PATCH 061/299] reimplement: SHC_3BB0A8C1_0x005343F0 100.00% Reimplemented --- .../setWorkplaceBuildingEntryAsTarget.cpp | 28 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/setWorkplaceBuildingEntryAsTarget.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/setWorkplaceBuildingEntryAsTarget.cpp b/src/OpenSHC/Map/Units/UnitsState/setWorkplaceBuildingEntryAsTarget.cpp new file mode 100644 index 000000000..c783dd310 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/setWorkplaceBuildingEntryAsTarget.cpp @@ -0,0 +1,28 @@ +#include "OpenSHC/Map/Buildings/BuildingsState.func.hpp" +#include "OpenSHC/Map/Units/UnitsState.func.hpp" + +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + // FUNCTION: STRONGHOLDCRUSADER 0x005343F0 + undefined4 UnitsState::setWorkplaceBuildingEntryAsTarget(int unitID, int entryAngleUnk) + { + int _buildingID = this->units[unitID].workplaceBuildingID_1; + if (DAT_BuildingsState::instance.buildings[_buildingID].uid == this->units[unitID].workplaceBuildingUID) { + if (MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::buildingIsAccessible, + DAT_BuildingsState::ptr)(_buildingID, entryAngleUnk) + != 0) { + this->units[unitID].targetX_2 = DAT_BuildingsState::instance.buildings[_buildingID].buildingEntryX; + this->units[unitID].targetY_2 = DAT_BuildingsState::instance.buildings[_buildingID].buildingEntryY; + return 1; + } + } + return 0; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 20ffd67ce..60b787a14 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -50807,7 +50807,7 @@ SHC_3BB0A8C1_0x00534380 | 77.6% | orig walks matrix row ptr SHC_3BB0A8C1_0x005343C0 | 0.0% | Pending -SHC_3BB0A8C1_0x005343F0 | 0.0% | Pending +SHC_3BB0A8C1_0x005343F0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00534460 | 100.0% | Reimplemented From 09daa29cad6e0f37b385e6c0203ea345b6626ba7 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:18 +0200 Subject: [PATCH 062/299] reimplement: SHC_3BB0A8C1_0x00537130 40.00% param store order differs --- .../queueDisbandAndAttackCommand3Params.cpp | 25 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/queueDisbandAndAttackCommand3Params.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/queueDisbandAndAttackCommand3Params.cpp b/src/OpenSHC/Map/Units/UnitsState/queueDisbandAndAttackCommand3Params.cpp new file mode 100644 index 000000000..0f4ff200d --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/queueDisbandAndAttackCommand3Params.cpp @@ -0,0 +1,25 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Synchrony/GameSynchronyState.func.hpp" +#include "OpenSHC/Commands/GameCommandType.hpp" + +#include "OpenSHC/Globals/DAT_GameSynchronyState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Commands::GameCommandType; + + // FUNCTION: STRONGHOLDCRUSADER 0x00537130 + void UnitsState::queueDisbandAndAttackCommand3Params(undefined4 param_1, undefined4 param_2, undefined4 param_3) + { + DAT_GameSynchronyState::instance.DAT_GameCommandParam1 = param_2; + DAT_GameSynchronyState::instance.DAT_GameCommandParam0 = param_1; + DAT_GameSynchronyState::instance.DAT_GameCommandParam2 = param_3; + MACRO_CALL_MEMBER(OpenSHC::Synchrony::GameSynchronyState_Func::queueCommand, DAT_GameSynchronyState::ptr)( + OpenSHC::Commands::GCT_DISBAND_AND_ATTACK_UNITS); + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 60b787a14..5c9ae9ff8 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -51225,7 +51225,7 @@ SHC_3BB0A8C1_0x005370C0 | 0.0% | Pending SHC_3BB0A8C1_0x00537100 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x00537130 | 0.0% | Pending +SHC_3BB0A8C1_0x00537130 | 40.0% | param store order differs SHC_3BB0A8C1_0x00537160 | 0.0% | Pending From 1356c60e7908001a7bd28b224ae37c602092c1b4 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:19 +0200 Subject: [PATCH 063/299] reimplement: SHC_3BB0A8C1_0x0052F550 100.00% Reimplemented --- .../ifAnyUnitOnSameTileIsLadder.cpp | 31 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/ifAnyUnitOnSameTileIsLadder.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/ifAnyUnitOnSameTileIsLadder.cpp b/src/OpenSHC/Map/Units/UnitsState/ifAnyUnitOnSameTileIsLadder.cpp new file mode 100644 index 000000000..bad0f97d8 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/ifAnyUnitOnSameTileIsLadder.cpp @@ -0,0 +1,31 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Map/Units/States/UnitState.hpp" +#include "OpenSHC/Map/Units/UnitType.hpp" +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +#include "OpenSHC/Globals/DAT_TileMapState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Map::Units::UnitType; + using OpenSHC::Map::Units::States::UnitState; + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x0052F550 + BOOLEnum UnitsState::ifAnyUnitOnSameTileIsLadder(int tile) + { + for (int unitID = (short)DAT_TileMapState::instance.UnitLayer[tile]; unitID != 0; + unitID = (short)this->units[unitID].nextUnitOnTheSameTile) { + if (this->units[unitID].unitType == OpenSHC::Map::Units::UT_E_LADDER + && this->units[unitID].state.generic == (UnitState)3) { + return TRUE; + } + } + return FALSE; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 5c9ae9ff8..fe1af03e7 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -49331,7 +49331,7 @@ SHC_3BB0A8C1_0x0052F4A0 | 0.0% | Pending SHC_3BB0A8C1_0x0052F4E0 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x0052F550 | 0.0% | Pending +SHC_3BB0A8C1_0x0052F550 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0052F570 | 0.0% | Pending From 80d7d4d4764c36923d8671579a5d5c7407d5df07 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:19 +0200 Subject: [PATCH 064/299] reimplement: SHC_3BB0A8C1_0x0053BB90 60.00% one read via global inst --- .../UnitsState/teleportUnitToUnitXAndY.cpp | 29 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/teleportUnitToUnitXAndY.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/teleportUnitToUnitXAndY.cpp b/src/OpenSHC/Map/Units/UnitsState/teleportUnitToUnitXAndY.cpp new file mode 100644 index 000000000..de9ec54a2 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/teleportUnitToUnitXAndY.cpp @@ -0,0 +1,29 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" + +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + // FUNCTION: STRONGHOLDCRUSADER 0x0053BB90 + void UnitsState::teleportUnitToUnitXAndY(int unitID) + { + int _tileY = DAT_ViewportRenderState::instance.tileTranslationMatrix_YComponent[this->units[unitID].tile]; + int _tileX + = this->units[unitID].tile - DAT_ViewportRenderState::instance.translationMatrix[_tileY].addXgetTile; + if (_tileY == this->units[unitID].y && _tileX == this->units[unitID].x) { + return; + } + this->units[unitID].microXPosition = (short)(_tileX * 8 + 4); + this->units[unitID].microYPosition = (short)(_tileY * 8 + 4); + this->units[unitID].mimicCurrentXPosition = (short)_tileX; + this->units[unitID].x = (short)_tileX; + this->units[unitID].mimicCurrentYPosition = (short)_tileY; + this->units[unitID].y = (short)_tileY; + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::updateMicroPosition, this)(unitID); + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index fe1af03e7..65972fd8c 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -59657,7 +59657,7 @@ SHC_3BB0A8C1_0x0053BB10 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0053BB70 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x0053BB90 | 0.0% | Pending +SHC_3BB0A8C1_0x0053BB90 | 60.0% | one read via global inst SHC_3BB0A8C1_0x0053BC20 | 0.0% | Pending From 24293d3ac3e33ebbf8d4fa5aac24a7d99274538b Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:20 +0200 Subject: [PATCH 065/299] reimplement: SHC_3BB0A8C1_0x005370C0 100.00% Reimplemented --- .../Map/Units/UnitsState/extendRallyPoint.cpp | 26 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/extendRallyPoint.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/extendRallyPoint.cpp b/src/OpenSHC/Map/Units/UnitsState/extendRallyPoint.cpp new file mode 100644 index 000000000..17d16073c --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/extendRallyPoint.cpp @@ -0,0 +1,26 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Synchrony/GameSynchronyState.func.hpp" +#include "OpenSHC/Commands/GameCommandType.hpp" + +#include "OpenSHC/Globals/DAT_GameSynchronyState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Commands::GameCommandType; + + // FUNCTION: STRONGHOLDCRUSADER 0x005370C0 + void UnitsState::extendRallyPoint(int tribeID, int mouseX, int mouseY, int rallyCount) + { + DAT_GameSynchronyState::instance.DAT_GameCommandParam0 = tribeID; + DAT_GameSynchronyState::instance.DAT_GameCommandParam1 = mouseX; + DAT_GameSynchronyState::instance.DAT_GameCommandParam2 = mouseY; + DAT_GameSynchronyState::instance.DAT_GameCommandParam3 = rallyCount; + MACRO_CALL_MEMBER(OpenSHC::Synchrony::GameSynchronyState_Func::queueCommand, DAT_GameSynchronyState::ptr)( + OpenSHC::Commands::GCT_UNIT_EXTEND_RALLY_POINT); + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 65972fd8c..bac20db0c 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -51221,7 +51221,7 @@ SHC_3BB0A8C1_0x00536E30 | 0.0% | Pending SHC_3BB0A8C1_0x00537070 | 86.4% | enum cast, reg alloc -SHC_3BB0A8C1_0x005370C0 | 0.0% | Pending +SHC_3BB0A8C1_0x005370C0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00537100 | 100.0% | Reimplemented From 3f430a9f49a2530f8f193ca3274fd3953be47a39 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:20 +0200 Subject: [PATCH 066/299] reimplement: SHC_3BB0A8C1_0x0052F440 66.67% loop shape differs --- .../UnitsState/setupUnitSharingTileIDs.cpp | 35 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/setupUnitSharingTileIDs.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/setupUnitSharingTileIDs.cpp b/src/OpenSHC/Map/Units/UnitsState/setupUnitSharingTileIDs.cpp new file mode 100644 index 000000000..c92ccdf7b --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/setupUnitSharingTileIDs.cpp @@ -0,0 +1,35 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" + +#include "OpenSHC/Globals/DAT_TileMapState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + // FUNCTION: STRONGHOLDCRUSADER 0x0052F440 + void UnitsState::setupUnitSharingTileIDs(int unitID, int unitCurrentTilePosition) + { + if (unitCurrentTilePosition == 0) { + return; + } + this->units[unitID].unitOrderWhenOnSameTile = 0; + if ((short)DAT_TileMapState::instance.UnitLayer[unitCurrentTilePosition] == unitID) { + DAT_TileMapState::instance.UnitLayer[unitCurrentTilePosition] + = this->units[unitID].nextUnitOnTheSameTile; + this->units[unitID].nextUnitOnTheSameTile = 0; + return; + } + int _previousUnitID = (short)DAT_TileMapState::instance.UnitLayer[unitCurrentTilePosition]; + while (_previousUnitID != 0 && (short)this->units[_previousUnitID].nextUnitOnTheSameTile != unitID) { + _previousUnitID = (short)this->units[_previousUnitID].nextUnitOnTheSameTile; + if (_previousUnitID == 0) { + return; + } + } + this->units[_previousUnitID].nextUnitOnTheSameTile = this->units[unitID].nextUnitOnTheSameTile; + this->units[unitID].nextUnitOnTheSameTile = 0; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index bac20db0c..b3916d37a 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -49325,7 +49325,7 @@ SHC_3BB0A8C1_0x0052F0D0 | 0.0% | Pending SHC_3BB0A8C1_0x0052F260 | 0.0% | Pending -SHC_3BB0A8C1_0x0052F440 | 0.0% | Pending +SHC_3BB0A8C1_0x0052F440 | 66.7% | loop shape differs SHC_3BB0A8C1_0x0052F4A0 | 0.0% | Pending From 5f110746ecabacf72ecf071780813473dc6aba93 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:20 +0200 Subject: [PATCH 067/299] reimplement: SHC_3BB0A8C1_0x00530880 100.00% Reimplemented --- .../UnitsState/setRandomNumberOnCows.cpp | 31 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/setRandomNumberOnCows.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/setRandomNumberOnCows.cpp b/src/OpenSHC/Map/Units/UnitsState/setRandomNumberOnCows.cpp new file mode 100644 index 000000000..247891283 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/setRandomNumberOnCows.cpp @@ -0,0 +1,31 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Random/RNG.func.hpp" +#include "OpenSHC/Map/Units/UnitLogicState.hpp" +#include "OpenSHC/Map/Units/UnitType.hpp" + +#include "OpenSHC/Globals/SEC_RNG.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Map::Units::UnitLogicState; + using OpenSHC::Map::Units::UnitType; + + // FUNCTION: STRONGHOLDCRUSADER 0x00530880 + void UnitsState::setRandomNumberOnCows(int playerID) + { + for (int unitID = 0; unitID < (int)this->maxUnitCount; ++unitID) { + if (this->units[unitID].logicalState == OpenSHC::Map::Units::ULS_NORMAL + && this->units[unitID].dying == 0 && this->units[unitID].unitType == OpenSHC::Map::Units::UT_COW + && this->units[unitID].owner == playerID) { + this->units[unitID].digTileX__OR__countCurrentlyManningEnginers__OR__forCowsRandomBelow300 + = SEC_RNG::instance.currentNumber2 % 300; + MACRO_CALL_MEMBER(OpenSHC::Random::RNG_Func::nextRandomNumber2, SEC_RNG::ptr)(); + } + } + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index b3916d37a..fe76fbbb0 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -49633,7 +49633,7 @@ SHC_3BB0A8C1_0x00530760 | 0.0% | Pending SHC_3BB0A8C1_0x005307B0 | 0.0% | Pending -SHC_3BB0A8C1_0x00530880 | 0.0% | Pending +SHC_3BB0A8C1_0x00530880 | 100.0% | Reimplemented SHC_3BB0A8C1_0x005308F0 | 0.0% | Pending From f9234690eac29006a145dc1762da35c2eaf5d6ca Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:21 +0200 Subject: [PATCH 068/299] reimplement: SHC_3BB0A8C1_0x00535730 100.00% Reimplemented --- .../selectionContainsRangedOnlyUnits.cpp | 30 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/selectionContainsRangedOnlyUnits.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/selectionContainsRangedOnlyUnits.cpp b/src/OpenSHC/Map/Units/UnitsState/selectionContainsRangedOnlyUnits.cpp new file mode 100644 index 000000000..da6708ed7 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/selectionContainsRangedOnlyUnits.cpp @@ -0,0 +1,30 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x00535730 + BOOLEnum UnitsState::selectionContainsRangedOnlyUnits() + { + if (this->selectionEuropeanArchers != 0 || this->selectionCrossbowmen != 0 || this->selectionArabArcher != 0 + || this->selectionArabSlinger != 0 || this->selectionArabHorseArchers != 0 + || this->selectionArabFireThrower != 0 || this->selectionFireBallista != 0 + || this->selectionCatapults != 0 || this->selectionTrebuchets != 0) { + for (int i = 0; i <= 26; ++i) { + if (i != 0 && i != 3 && i != 19 && i != 21 && i != 23 && i != 25 && i != 26 && i != 11 && i != 12 + && (&this->selectionEuropeanArchers)[i] != 0) { + return FALSE; + } + } + return TRUE; + } + return FALSE; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index fe76fbbb0..4ea309464 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -51079,7 +51079,7 @@ SHC_3BB0A8C1_0x00535680 | 0.0% | Pending SHC_3BB0A8C1_0x00535700 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x00535730 | 0.0% | Pending +SHC_3BB0A8C1_0x00535730 | 100.0% | Reimplemented SHC_3BB0A8C1_0x005357E0 | 100.0% | Reimplemented From 476713ce24aace0f06d83353cfac521b5fd07496 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:21 +0200 Subject: [PATCH 069/299] reimplement: SHC_3BB0A8C1_0x005365A0 100.00% Reimplemented --- .../getFirstSelectedLadderUnitID.cpp | 42 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/getFirstSelectedLadderUnitID.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/getFirstSelectedLadderUnitID.cpp b/src/OpenSHC/Map/Units/UnitsState/getFirstSelectedLadderUnitID.cpp new file mode 100644 index 000000000..6098cd568 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/getFirstSelectedLadderUnitID.cpp @@ -0,0 +1,42 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Map/Units/UnitLogicState.hpp" +#include "OpenSHC/Map/Units/UnitType.hpp" + +#include "OpenSHC/Globals/DAT_CurrentUnitSlotID.hpp" +#include "OpenSHC/Globals/DAT_GameSynchronyState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Map::Units::UnitLogicState; + using OpenSHC::Map::Units::UnitType; + + // FUNCTION: STRONGHOLDCRUSADER 0x005365A0 + uint UnitsState::getFirstSelectedLadderUnitID() + { + int _currentPlayerSlotID = DAT_GameSynchronyState::instance.currentPlayerSlotID; + for (DAT_CurrentUnitSlotID::instance = 1; (int)DAT_CurrentUnitSlotID::instance < (int)this->maxUnitCount; + DAT_CurrentUnitSlotID::instance = DAT_CurrentUnitSlotID::instance + 1) { + if (this->units[DAT_CurrentUnitSlotID::instance].logicalState != OpenSHC::Map::Units::ULS_NORMAL) { + continue; + } + if (this->units[DAT_CurrentUnitSlotID::instance].dying != 0) { + continue; + } + if (this->units[DAT_CurrentUnitSlotID::instance].isSelected == 0) { + continue; + } + if (this->units[DAT_CurrentUnitSlotID::instance].owner != _currentPlayerSlotID) { + return 0; + } + if (this->units[DAT_CurrentUnitSlotID::instance].unitType == OpenSHC::Map::Units::UT_E_LADDER) { + return DAT_CurrentUnitSlotID::instance; + } + } + return 0; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 4ea309464..a679e54ff 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -51133,7 +51133,7 @@ SHC_3BB0A8C1_0x005364C0 | 0.0% | Pending SHC_3BB0A8C1_0x00536530 | 0.0% | Pending -SHC_3BB0A8C1_0x005365A0 | 0.0% | Pending +SHC_3BB0A8C1_0x005365A0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00536610 | 0.0% | Pending From f597be5eb316462a6ae621d6ff0cf6e9859e2ffa Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:21 +0200 Subject: [PATCH 070/299] reimplement: SHC_3BB0A8C1_0x005364C0 100.00% Reimplemented --- .../returnFirstSelectedEngineer.cpp | 42 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/returnFirstSelectedEngineer.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/returnFirstSelectedEngineer.cpp b/src/OpenSHC/Map/Units/UnitsState/returnFirstSelectedEngineer.cpp new file mode 100644 index 000000000..f3b5dfd47 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/returnFirstSelectedEngineer.cpp @@ -0,0 +1,42 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Map/Units/UnitLogicState.hpp" +#include "OpenSHC/Map/Units/UnitType.hpp" + +#include "OpenSHC/Globals/DAT_CurrentUnitSlotID.hpp" +#include "OpenSHC/Globals/DAT_GameSynchronyState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Map::Units::UnitLogicState; + using OpenSHC::Map::Units::UnitType; + + // FUNCTION: STRONGHOLDCRUSADER 0x005364C0 + uint UnitsState::returnFirstSelectedEngineer() + { + int _currentPlayerSlotID = DAT_GameSynchronyState::instance.currentPlayerSlotID; + for (DAT_CurrentUnitSlotID::instance = 1; (int)DAT_CurrentUnitSlotID::instance < (int)this->maxUnitCount; + DAT_CurrentUnitSlotID::instance = DAT_CurrentUnitSlotID::instance + 1) { + if (this->units[DAT_CurrentUnitSlotID::instance].logicalState != OpenSHC::Map::Units::ULS_NORMAL) { + continue; + } + if (this->units[DAT_CurrentUnitSlotID::instance].dying != 0) { + continue; + } + if (this->units[DAT_CurrentUnitSlotID::instance].isSelected == 0) { + continue; + } + if (this->units[DAT_CurrentUnitSlotID::instance].owner != _currentPlayerSlotID) { + return 0; + } + if (this->units[DAT_CurrentUnitSlotID::instance].unitType == OpenSHC::Map::Units::UT_E_ENGINEER) { + return DAT_CurrentUnitSlotID::instance; + } + } + return 0; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index a679e54ff..8271d609d 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -51129,7 +51129,7 @@ SHC_3BB0A8C1_0x00536400 | 0.0% | Pending SHC_3BB0A8C1_0x00536440 | 0.0% | Pending -SHC_3BB0A8C1_0x005364C0 | 0.0% | Pending +SHC_3BB0A8C1_0x005364C0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00536530 | 0.0% | Pending From dad095526746fd23e3e08dd74faf4f96868c2bf8 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:22 +0200 Subject: [PATCH 071/299] reimplement: SHC_3BB0A8C1_0x00536530 100.00% Reimplemented --- .../getTunnelerIDOnlyIfFirstSelected.cpp | 42 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/getTunnelerIDOnlyIfFirstSelected.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/getTunnelerIDOnlyIfFirstSelected.cpp b/src/OpenSHC/Map/Units/UnitsState/getTunnelerIDOnlyIfFirstSelected.cpp new file mode 100644 index 000000000..8a16c824a --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/getTunnelerIDOnlyIfFirstSelected.cpp @@ -0,0 +1,42 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Map/Units/UnitLogicState.hpp" +#include "OpenSHC/Map/Units/UnitType.hpp" + +#include "OpenSHC/Globals/DAT_CurrentUnitSlotID.hpp" +#include "OpenSHC/Globals/DAT_GameSynchronyState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Map::Units::UnitLogicState; + using OpenSHC::Map::Units::UnitType; + + // FUNCTION: STRONGHOLDCRUSADER 0x00536530 + uint UnitsState::getTunnelerIDOnlyIfFirstSelected() + { + int _currentPlayerSlotID = DAT_GameSynchronyState::instance.currentPlayerSlotID; + for (DAT_CurrentUnitSlotID::instance = 1; (int)DAT_CurrentUnitSlotID::instance < (int)this->maxUnitCount; + DAT_CurrentUnitSlotID::instance = DAT_CurrentUnitSlotID::instance + 1) { + if (this->units[DAT_CurrentUnitSlotID::instance].logicalState != OpenSHC::Map::Units::ULS_NORMAL) { + continue; + } + if (this->units[DAT_CurrentUnitSlotID::instance].dying != 0) { + continue; + } + if (this->units[DAT_CurrentUnitSlotID::instance].isSelected == 0) { + continue; + } + if (this->units[DAT_CurrentUnitSlotID::instance].owner != _currentPlayerSlotID) { + return 0; + } + if (this->units[DAT_CurrentUnitSlotID::instance].unitType == OpenSHC::Map::Units::UT_TUNNELER) { + return DAT_CurrentUnitSlotID::instance; + } + } + return 0; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 8271d609d..1351c24ed 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -51131,7 +51131,7 @@ SHC_3BB0A8C1_0x00536440 | 0.0% | Pending SHC_3BB0A8C1_0x005364C0 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x00536530 | 0.0% | Pending +SHC_3BB0A8C1_0x00536530 | 100.0% | Reimplemented SHC_3BB0A8C1_0x005365A0 | 100.0% | Reimplemented From 5c25dae2b9c9644d03179b923d3c891eacfc588b Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:22 +0200 Subject: [PATCH 072/299] reimplement: SHC_3BB0A8C1_0x005359C0 100.00% Reimplemented --- ...etSelectedLordIDIfOwnedByCurrentPlayer.cpp | 42 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/getSelectedLordIDIfOwnedByCurrentPlayer.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/getSelectedLordIDIfOwnedByCurrentPlayer.cpp b/src/OpenSHC/Map/Units/UnitsState/getSelectedLordIDIfOwnedByCurrentPlayer.cpp new file mode 100644 index 000000000..9db6c3340 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/getSelectedLordIDIfOwnedByCurrentPlayer.cpp @@ -0,0 +1,42 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Map/Units/UnitLogicState.hpp" +#include "OpenSHC/Map/Units/UnitType.hpp" + +#include "OpenSHC/Globals/DAT_CurrentUnitSlotID.hpp" +#include "OpenSHC/Globals/DAT_GameSynchronyState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Map::Units::UnitLogicState; + using OpenSHC::Map::Units::UnitType; + + // FUNCTION: STRONGHOLDCRUSADER 0x005359C0 + uint UnitsState::getSelectedLordIDIfOwnedByCurrentPlayer() + { + int _currentPlayerSlotID = DAT_GameSynchronyState::instance.currentPlayerSlotID; + for (DAT_CurrentUnitSlotID::instance = 1; (int)DAT_CurrentUnitSlotID::instance < (int)this->maxUnitCount; + DAT_CurrentUnitSlotID::instance = DAT_CurrentUnitSlotID::instance + 1) { + if (this->units[DAT_CurrentUnitSlotID::instance].logicalState != OpenSHC::Map::Units::ULS_NORMAL) { + continue; + } + if (this->units[DAT_CurrentUnitSlotID::instance].dying != 0) { + continue; + } + if (this->units[DAT_CurrentUnitSlotID::instance].isSelected == 0) { + continue; + } + if (this->units[DAT_CurrentUnitSlotID::instance].owner != _currentPlayerSlotID) { + return 0; + } + if (this->units[DAT_CurrentUnitSlotID::instance].unitType == OpenSHC::Map::Units::UT_LORD) { + return DAT_CurrentUnitSlotID::instance; + } + } + return 0; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 1351c24ed..751e7803c 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -51095,7 +51095,7 @@ SHC_3BB0A8C1_0x00535910 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00535980 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x005359C0 | 0.0% | Pending +SHC_3BB0A8C1_0x005359C0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00535A30 | 0.0% | Pending From e33523defaafbc63643e885f66b4e771f0c1c732 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:23 +0200 Subject: [PATCH 073/299] reimplement: SHC_3BB0A8C1_0x00536710 100.00% Reimplemented --- .../getFirstSelectedCatapultOrTrebuchetID.cpp | 45 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/getFirstSelectedCatapultOrTrebuchetID.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/getFirstSelectedCatapultOrTrebuchetID.cpp b/src/OpenSHC/Map/Units/UnitsState/getFirstSelectedCatapultOrTrebuchetID.cpp new file mode 100644 index 000000000..393795eaf --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/getFirstSelectedCatapultOrTrebuchetID.cpp @@ -0,0 +1,45 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Map/Units/UnitLogicState.hpp" +#include "OpenSHC/Map/Units/UnitType.hpp" + +#include "OpenSHC/Globals/DAT_CurrentUnitSlotID.hpp" +#include "OpenSHC/Globals/DAT_GameSynchronyState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Map::Units::UnitLogicState; + using OpenSHC::Map::Units::UnitType; + + // FUNCTION: STRONGHOLDCRUSADER 0x00536710 + uint UnitsState::getFirstSelectedCatapultOrTrebuchetID() + { + int _currentPlayerSlotID = DAT_GameSynchronyState::instance.currentPlayerSlotID; + for (DAT_CurrentUnitSlotID::instance = 1; (int)DAT_CurrentUnitSlotID::instance < (int)this->maxUnitCount; + DAT_CurrentUnitSlotID::instance = DAT_CurrentUnitSlotID::instance + 1) { + if (this->units[DAT_CurrentUnitSlotID::instance].logicalState != OpenSHC::Map::Units::ULS_NORMAL) { + continue; + } + if (this->units[DAT_CurrentUnitSlotID::instance].dying != 0) { + continue; + } + if (this->units[DAT_CurrentUnitSlotID::instance].isSelected == 0) { + continue; + } + if (this->units[DAT_CurrentUnitSlotID::instance].owner != _currentPlayerSlotID) { + return 0; + } + if (this->units[DAT_CurrentUnitSlotID::instance].unitType == OpenSHC::Map::Units::UT_S_CATAPULT) { + return DAT_CurrentUnitSlotID::instance; + } + if (this->units[DAT_CurrentUnitSlotID::instance].unitType == OpenSHC::Map::Units::UT_S_TREBUCHET) { + return DAT_CurrentUnitSlotID::instance; + } + } + return 0; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 751e7803c..d5b5dd911 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -51141,7 +51141,7 @@ SHC_3BB0A8C1_0x00536630 | 0.0% | Pending SHC_3BB0A8C1_0x00536690 | 0.0% | Pending -SHC_3BB0A8C1_0x00536710 | 0.0% | Pending +SHC_3BB0A8C1_0x00536710 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00536780 | 0.0% | Pending From 93a0238939eb614ddc5e79c5faa4a53c8e9adfb8 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:23 +0200 Subject: [PATCH 074/299] reimplement: SHC_3BB0A8C1_0x005361F0 100.00% Reimplemented --- .../getUnitTypeOfFirstSelectedUnit.cpp | 40 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/getUnitTypeOfFirstSelectedUnit.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/getUnitTypeOfFirstSelectedUnit.cpp b/src/OpenSHC/Map/Units/UnitsState/getUnitTypeOfFirstSelectedUnit.cpp new file mode 100644 index 000000000..2ab5e6f23 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/getUnitTypeOfFirstSelectedUnit.cpp @@ -0,0 +1,40 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Map/Units/UnitLogicState.hpp" +#include "OpenSHC/Map/Units/UnitType.hpp" + +#include "OpenSHC/Globals/DAT_CurrentUnitSlotID.hpp" +#include "OpenSHC/Globals/DAT_GameSynchronyState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Map::Units::UnitLogicState; + using OpenSHC::Map::Units::UnitType; + + // FUNCTION: STRONGHOLDCRUSADER 0x005361F0 + UnitType UnitsState::getUnitTypeOfFirstSelectedUnit() + { + int _currentPlayerSlotID = DAT_GameSynchronyState::instance.currentPlayerSlotID; + for (DAT_CurrentUnitSlotID::instance = 1; (int)DAT_CurrentUnitSlotID::instance < (int)this->maxUnitCount; + DAT_CurrentUnitSlotID::instance = DAT_CurrentUnitSlotID::instance + 1) { + if (this->units[DAT_CurrentUnitSlotID::instance].logicalState != OpenSHC::Map::Units::ULS_NORMAL) { + continue; + } + if (this->units[DAT_CurrentUnitSlotID::instance].dying != 0) { + continue; + } + if (this->units[DAT_CurrentUnitSlotID::instance].isSelected == 0) { + continue; + } + if (this->units[DAT_CurrentUnitSlotID::instance].owner != _currentPlayerSlotID) { + return (UnitType)-1; + } + return (UnitType)(short)this->units[DAT_CurrentUnitSlotID::instance].unitType; + } + return (UnitType)0; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index d5b5dd911..59f6bbe37 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -51113,7 +51113,7 @@ SHC_3BB0A8C1_0x005360A0 | 0.0% | Pending SHC_3BB0A8C1_0x00536190 | 72.4% | incr scheduled before call -SHC_3BB0A8C1_0x005361F0 | 0.0% | Pending +SHC_3BB0A8C1_0x005361F0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00536260 | 0.0% | Pending From 8942c4feb136cb2a2f0105e57b041e7a75212eb7 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:23 +0200 Subject: [PATCH 075/299] reimplement: SHC_3BB0A8C1_0x005362F0 100.00% Reimplemented --- .../getFirstSelectedUnitOfEitherType.cpp | 43 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/getFirstSelectedUnitOfEitherType.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/getFirstSelectedUnitOfEitherType.cpp b/src/OpenSHC/Map/Units/UnitsState/getFirstSelectedUnitOfEitherType.cpp new file mode 100644 index 000000000..e4025d738 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/getFirstSelectedUnitOfEitherType.cpp @@ -0,0 +1,43 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Map/Units/UnitLogicState.hpp" + +#include "OpenSHC/Globals/DAT_CurrentUnitSlotID.hpp" +#include "OpenSHC/Globals/DAT_GameSynchronyState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Map::Units::UnitLogicState; + + // FUNCTION: STRONGHOLDCRUSADER 0x005362F0 + uint UnitsState::getFirstSelectedUnitOfEitherType(int unitType_1, int unitType_2) + { + int _currentPlayerSlotID = DAT_GameSynchronyState::instance.currentPlayerSlotID; + for (DAT_CurrentUnitSlotID::instance = 1; (int)DAT_CurrentUnitSlotID::instance < (int)this->maxUnitCount; + DAT_CurrentUnitSlotID::instance = DAT_CurrentUnitSlotID::instance + 1) { + if (this->units[DAT_CurrentUnitSlotID::instance].logicalState != OpenSHC::Map::Units::ULS_NORMAL) { + continue; + } + if (this->units[DAT_CurrentUnitSlotID::instance].dying != 0) { + continue; + } + if (this->units[DAT_CurrentUnitSlotID::instance].isSelected == 0) { + continue; + } + if (this->units[DAT_CurrentUnitSlotID::instance].owner != _currentPlayerSlotID) { + return 0; + } + if ((short)this->units[DAT_CurrentUnitSlotID::instance].unitType == unitType_1) { + return DAT_CurrentUnitSlotID::instance; + } + if ((short)this->units[DAT_CurrentUnitSlotID::instance].unitType == unitType_2) { + return DAT_CurrentUnitSlotID::instance; + } + } + return 0; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 59f6bbe37..21d03b80e 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -51119,7 +51119,7 @@ SHC_3BB0A8C1_0x00536260 | 0.0% | Pending SHC_3BB0A8C1_0x00536280 | 0.0% | Pending -SHC_3BB0A8C1_0x005362F0 | 0.0% | Pending +SHC_3BB0A8C1_0x005362F0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00536310 | 0.0% | Pending From b0d792ccc2c842325dc335c295eb78d07b6d9009 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:24 +0200 Subject: [PATCH 076/299] reimplement: SHC_3BB0A8C1_0x00536610 100.00% Reimplemented --- .../Map/Units/UnitsState/canAUnitClimb.cpp | 40 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/canAUnitClimb.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/canAUnitClimb.cpp b/src/OpenSHC/Map/Units/UnitsState/canAUnitClimb.cpp new file mode 100644 index 000000000..8e8e3c8d2 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/canAUnitClimb.cpp @@ -0,0 +1,40 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Map/Units/UnitLogicState.hpp" + +#include "OpenSHC/Globals/DAT_CurrentUnitSlotID.hpp" +#include "OpenSHC/Globals/DAT_GameSynchronyState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Map::Units::UnitLogicState; + + // FUNCTION: STRONGHOLDCRUSADER 0x00536610 + undefined4 UnitsState::canAUnitClimb() + { + int _currentPlayerSlotID = DAT_GameSynchronyState::instance.currentPlayerSlotID; + for (DAT_CurrentUnitSlotID::instance = 1; (int)DAT_CurrentUnitSlotID::instance < (int)this->maxUnitCount; + DAT_CurrentUnitSlotID::instance = DAT_CurrentUnitSlotID::instance + 1) { + if (this->units[DAT_CurrentUnitSlotID::instance].logicalState != OpenSHC::Map::Units::ULS_NORMAL) { + continue; + } + if (this->units[DAT_CurrentUnitSlotID::instance].dying != 0) { + continue; + } + if (this->units[DAT_CurrentUnitSlotID::instance].isSelected == 0) { + continue; + } + if (this->units[DAT_CurrentUnitSlotID::instance].owner != _currentPlayerSlotID) { + return 0; + } + if (this->units[DAT_CurrentUnitSlotID::instance].unitCanClimb != 0) { + return 1; + } + } + return 0; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 21d03b80e..b8766d695 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -51135,7 +51135,7 @@ SHC_3BB0A8C1_0x00536530 | 100.0% | Reimplemented SHC_3BB0A8C1_0x005365A0 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x00536610 | 0.0% | Pending +SHC_3BB0A8C1_0x00536610 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00536630 | 0.0% | Pending From a395f167875ff98065b2acf234692230c3be73e7 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:24 +0200 Subject: [PATCH 077/299] reimplement: SHC_3BB0A8C1_0x0053E9F0 56.79% orig caches x/y in locals --- .../Units/UnitsState/commitMimmicLocation.cpp | 31 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/commitMimmicLocation.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/commitMimmicLocation.cpp b/src/OpenSHC/Map/Units/UnitsState/commitMimmicLocation.cpp new file mode 100644 index 000000000..fdbf2c75e --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/commitMimmicLocation.cpp @@ -0,0 +1,31 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" + +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + // FUNCTION: STRONGHOLDCRUSADER 0x0053E9F0 + void UnitsState::commitMimmicLocation(int unitID) + { + this->units[unitID].movementRelated = 8; + this->units[unitID].field105_0xe8 = 0; + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::setupUnitSharingCurrentTilePosition, this)(unitID); + this->units[unitID].y = this->units[unitID].mimicCurrentYPosition; + this->units[unitID].microXPosition = this->units[unitID].mimicCurrentXPosition * 8 + 4; + this->units[unitID].x = this->units[unitID].mimicCurrentXPosition; + this->units[unitID].microYPosition = this->units[unitID].mimicCurrentYPosition * 8 + 4; + this->units[unitID].tile = this->units[unitID].mimicCurrentXPosition + + DAT_ViewportRenderState::instance.translationMatrix[this->units[unitID].mimicCurrentYPosition] + .addXgetTile; + this->units[unitID].terrainOrClimbHeight = DAT_TileMapState::instance.HeightLayer[this->units[unitID].tile]; + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::commitPendingUnitPosition, this)(unitID); + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::updateMicroPosition, this)(unitID); + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::recomputeUnitStandingHeight, this)(unitID); + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index b8766d695..2319010f2 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -60099,7 +60099,7 @@ SHC_3BB0A8C1_0x0053E8D0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0053E900 | 0.0% | Pending -SHC_3BB0A8C1_0x0053E9F0 | 0.0% | Pending +SHC_3BB0A8C1_0x0053E9F0 | 56.8% | orig caches x/y in locals SHC_3BB0A8C1_0x0053EAA0 | 0.0% | Pending From 422e75c278f2d6c88aaeb6f7f1c8bdb1c0ecb668 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:24 +0200 Subject: [PATCH 078/299] reimplement: SHC_3BB0A8C1_0x00536260 65.00% type range test shape --- .../selectionHasMovableNonSiegeUnit.cpp | 46 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/selectionHasMovableNonSiegeUnit.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/selectionHasMovableNonSiegeUnit.cpp b/src/OpenSHC/Map/Units/UnitsState/selectionHasMovableNonSiegeUnit.cpp new file mode 100644 index 000000000..f6167c3f9 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/selectionHasMovableNonSiegeUnit.cpp @@ -0,0 +1,46 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Map/Units/UnitLogicState.hpp" +#include "OpenSHC/Map/Units/UnitType.hpp" + +#include "OpenSHC/Globals/DAT_CurrentUnitSlotID.hpp" +#include "OpenSHC/Globals/DAT_GameSynchronyState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Map::Units::UnitLogicState; + using OpenSHC::Map::Units::UnitType; + + // FUNCTION: STRONGHOLDCRUSADER 0x00536260 + undefined4 UnitsState::selectionHasMovableNonSiegeUnit() + { + int _currentPlayerSlotID = DAT_GameSynchronyState::instance.currentPlayerSlotID; + for (DAT_CurrentUnitSlotID::instance = 1; (int)DAT_CurrentUnitSlotID::instance < (int)this->maxUnitCount; + DAT_CurrentUnitSlotID::instance = DAT_CurrentUnitSlotID::instance + 1) { + if (this->units[DAT_CurrentUnitSlotID::instance].logicalState != OpenSHC::Map::Units::ULS_NORMAL) { + continue; + } + if (this->units[DAT_CurrentUnitSlotID::instance].dying != 0) { + continue; + } + if (this->units[DAT_CurrentUnitSlotID::instance].isSelected == 0) { + continue; + } + if (this->units[DAT_CurrentUnitSlotID::instance].owner != _currentPlayerSlotID) { + return 0; + } + if ((short)this->units[DAT_CurrentUnitSlotID::instance].unitType < 40) { + return 1; + } + if ((short)this->units[DAT_CurrentUnitSlotID::instance].unitType > 41 + && this->units[DAT_CurrentUnitSlotID::instance].unitType != OpenSHC::Map::Units::UT_S_BALLISTA) { + return 1; + } + } + return 0; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 2319010f2..f969c8fae 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -51115,7 +51115,7 @@ SHC_3BB0A8C1_0x00536190 | 72.4% | incr scheduled before call SHC_3BB0A8C1_0x005361F0 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x00536260 | 0.0% | Pending +SHC_3BB0A8C1_0x00536260 | 65.0% | type range test shape SHC_3BB0A8C1_0x00536280 | 0.0% | Pending From bf37bd2c9e69a991a514a7c51645966e2222d778 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:25 +0200 Subject: [PATCH 079/299] reimplement: SHC_3BB0A8C1_0x00537160 100.00% Reimplemented --- .../queueDisbandAndAttackCommand4Params.cpp | 27 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/queueDisbandAndAttackCommand4Params.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/queueDisbandAndAttackCommand4Params.cpp b/src/OpenSHC/Map/Units/UnitsState/queueDisbandAndAttackCommand4Params.cpp new file mode 100644 index 000000000..b684a7927 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/queueDisbandAndAttackCommand4Params.cpp @@ -0,0 +1,27 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Synchrony/GameSynchronyState.func.hpp" +#include "OpenSHC/Commands/GameCommandType.hpp" + +#include "OpenSHC/Globals/DAT_GameSynchronyState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Commands::GameCommandType; + + // FUNCTION: STRONGHOLDCRUSADER 0x00537160 + void UnitsState::queueDisbandAndAttackCommand4Params( + undefined4 param_1, undefined4 param_2, undefined4 param_3, undefined4 param_4) + { + DAT_GameSynchronyState::instance.DAT_GameCommandParam0 = param_1; + DAT_GameSynchronyState::instance.DAT_GameCommandParam1 = param_2; + DAT_GameSynchronyState::instance.DAT_GameCommandParam2 = param_3; + DAT_GameSynchronyState::instance.DAT_GameCommandParam3 = param_4; + MACRO_CALL_MEMBER(OpenSHC::Synchrony::GameSynchronyState_Func::queueCommand, DAT_GameSynchronyState::ptr)( + OpenSHC::Commands::GCT_DISBAND_AND_ATTACK_UNITS); + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index f969c8fae..1f3580e32 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -51227,7 +51227,7 @@ SHC_3BB0A8C1_0x00537100 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00537130 | 40.0% | param store order differs -SHC_3BB0A8C1_0x00537160 | 0.0% | Pending +SHC_3BB0A8C1_0x00537160 | 100.0% | Reimplemented SHC_3BB0A8C1_0x005371A0 | 0.0% | Pending From 6ab5757b472557859b091b9c121b1bb36616deaf Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:25 +0200 Subject: [PATCH 080/299] reimplement: SHC_3BB0A8C1_0x005371A0 35.71% param store order differs --- .../queueDisbandAndAttackCommand5Params.cpp | 28 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/queueDisbandAndAttackCommand5Params.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/queueDisbandAndAttackCommand5Params.cpp b/src/OpenSHC/Map/Units/UnitsState/queueDisbandAndAttackCommand5Params.cpp new file mode 100644 index 000000000..0d827d249 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/queueDisbandAndAttackCommand5Params.cpp @@ -0,0 +1,28 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Synchrony/GameSynchronyState.func.hpp" +#include "OpenSHC/Commands/GameCommandType.hpp" + +#include "OpenSHC/Globals/DAT_GameSynchronyState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Commands::GameCommandType; + + // FUNCTION: STRONGHOLDCRUSADER 0x005371A0 + void UnitsState::queueDisbandAndAttackCommand5Params(undefined4 param_1, UnitInstructionType instruction, + undefined4 param_3, undefined4 param_4, undefined4 param_5) + { + DAT_GameSynchronyState::instance.DAT_GameCommandParam1 = instruction; + DAT_GameSynchronyState::instance.DAT_GameCommandParam0 = param_1; + DAT_GameSynchronyState::instance.DAT_GameCommandParam4 = param_5; + DAT_GameSynchronyState::instance.DAT_GameCommandParam2 = param_3; + DAT_GameSynchronyState::instance.DAT_GameCommandParam3 = param_4; + MACRO_CALL_MEMBER(OpenSHC::Synchrony::GameSynchronyState_Func::queueCommand, DAT_GameSynchronyState::ptr)( + OpenSHC::Commands::GCT_DISBAND_AND_ATTACK_UNITS); + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 1f3580e32..789a4751f 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -51229,7 +51229,7 @@ SHC_3BB0A8C1_0x00537130 | 40.0% | param store order differs SHC_3BB0A8C1_0x00537160 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x005371A0 | 0.0% | Pending +SHC_3BB0A8C1_0x005371A0 | 35.7% | param store order differs SHC_3BB0A8C1_0x005371E0 | 100.0% | Reimplemented From b67a3d24731317a9d7ae573a62876a8cedbd6948 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:26 +0200 Subject: [PATCH 081/299] reimplement: SHC_3BB0A8C1_0x0052F010 68.97% branch shape differs --- .../UnitsState/removeUnitFromItsTribe.cpp | 40 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/removeUnitFromItsTribe.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/removeUnitFromItsTribe.cpp b/src/OpenSHC/Map/Units/UnitsState/removeUnitFromItsTribe.cpp new file mode 100644 index 000000000..cbd03c775 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/removeUnitFromItsTribe.cpp @@ -0,0 +1,40 @@ +#include "OpenSHC/Map/Units/TribesState.func.hpp" +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Map/Units/UnitLogicState.hpp" +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +#include "OpenSHC/Globals/DAT_TribesState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Map::Units::UnitLogicState; + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x0052F010 + void UnitsState::removeUnitFromItsTribe(uint unitID, int unitUID) + { + if ((int)unitID < 1) { + return; + } + if (this->units[unitID].uid != unitUID) { + return; + } + int _tribeID = this->units[unitID].tribeID; + this->units[unitID].logicalState = OpenSHC::Map::Units::ULS_REMOVE; + if (_tribeID < 1) { + return; + } + if (MACRO_CALL_MEMBER(OpenSHC::Map::Units::TribesState_Func::tribeCorrespondsWithUID, DAT_TribesState::ptr)( + _tribeID, this->units[unitID].tribeUID) + == FALSE) { + return; + } + MACRO_CALL_MEMBER(OpenSHC::Map::Units::TribesState_Func::removeUnitFromTribe, DAT_TribesState::ptr)( + unitID, _tribeID); + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 789a4751f..430e82a68 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -49315,7 +49315,7 @@ SHC_3BB0A8C1_0x0052EDC0 | 0.0% | Pending SHC_3BB0A8C1_0x0052EED0 | 0.0% | Pending -SHC_3BB0A8C1_0x0052F010 | 0.0% | Pending +SHC_3BB0A8C1_0x0052F010 | 69.0% | branch shape differs SHC_3BB0A8C1_0x0052F070 | 100.0% | Reimplemented From 688fcf81b3faf27162ba3e114db3fdf6a2141dd3 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:26 +0200 Subject: [PATCH 082/299] reimplement: SHC_3BB0A8C1_0x00533FC0 70.83% branch shape differs --- .../UnitsState/despawnUnreachableUnit.cpp | 37 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/despawnUnreachableUnit.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/despawnUnreachableUnit.cpp b/src/OpenSHC/Map/Units/UnitsState/despawnUnreachableUnit.cpp new file mode 100644 index 000000000..229e6ad1b --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/despawnUnreachableUnit.cpp @@ -0,0 +1,37 @@ +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Map/Units/States/UnitState.hpp" + +#include "OpenSHC/Globals/DAT_PathFindingState.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Map::Units::States::UnitState; + + // FUNCTION: STRONGHOLDCRUSADER 0x00533FC0 + void UnitsState::despawnUnreachableUnit(int unitID) + { + if (this->units[unitID].isSelectable_OR_matchTime != 0) { + return; + } + if ((short)this->units[unitID].unitType >= 0x37 && (short)this->units[unitID].unitType <= 0x39) { + return; + } + if ((DAT_TileMapState::instance.LogicLayer[this->units[unitID].tile] & 0x100U) == 0) { + return; + } + if (MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::someBinaryAlgFunctionPathFinding, + DAT_PathFindingState::ptr)(unitID) + == 0) { + return; + } + this->units[unitID].state.generic = OpenSHC::Map::Units::States::US_DISAPPEAR; + this->units[unitID].disappearFadeAlphaCountdown = 0; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 430e82a68..06f0b51a0 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -50779,7 +50779,7 @@ SHC_3BB0A8C1_0x00533F85 | 0.0% | Pending SHC_3BB0A8C1_0x00533F90 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x00533FC0 | 0.0% | Pending +SHC_3BB0A8C1_0x00533FC0 | 70.8% | branch shape differs SHC_3BB0A8C1_0x00534030 | 0.0% | Pending From b44193d414b9b4a5bb4880f7a6257af2a2469f47 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:26 +0200 Subject: [PATCH 083/299] reimplement: SHC_3BB0A8C1_0x00530240 100.00% Reimplemented --- .../triggerStoneTowerDeathForPlayer.cpp | 32 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/triggerStoneTowerDeathForPlayer.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/triggerStoneTowerDeathForPlayer.cpp b/src/OpenSHC/Map/Units/UnitsState/triggerStoneTowerDeathForPlayer.cpp new file mode 100644 index 000000000..abeee848c --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/triggerStoneTowerDeathForPlayer.cpp @@ -0,0 +1,32 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Map/Units/States/UnitState.hpp" +#include "OpenSHC/Map/Units/UnitLogicState.hpp" +#include "OpenSHC/Map/Units/UnitType.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Map::Units::UnitLogicState; + using OpenSHC::Map::Units::UnitType; + using OpenSHC::Map::Units::States::UnitState; + + // FUNCTION: STRONGHOLDCRUSADER 0x00530240 + void UnitsState::triggerStoneTowerDeathForPlayer(int playerID) + { + for (int unitID = 1; unitID < (int)this->maxUnitCount; ++unitID) { + if (this->units[unitID].logicalState == OpenSHC::Map::Units::ULS_NORMAL + && this->units[unitID].dying == 0 && this->units[unitID].owner == playerID + && this->units[unitID].unitType == OpenSHC::Map::Units::UT_S_TOWER + && this->units[unitID].state.generic + == (OpenSHC::Map::Units::States::US_STAND_UPUnk | OpenSHC::Map::Units::States::US_IDLEUnk)) { + this->units[unitID].state.generic = OpenSHC::Map::Units::States::US_STONE_DEATH_01; + this->units[unitID].animationCycleNumber = 0; + this->units[unitID].dying = 1; + } + } + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 06f0b51a0..bee611c9c 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -49369,7 +49369,7 @@ SHC_3BB0A8C1_0x005301F0 | 96.0% | reg alloc differs SHC_3BB0A8C1_0x00530210 | 0.0% | Pending -SHC_3BB0A8C1_0x00530240 | 0.0% | Pending +SHC_3BB0A8C1_0x00530240 | 100.0% | Reimplemented SHC_3BB0A8C1_0x005302B0 | 100.0% | Reimplemented From 2d9498829784b3d54de2b8140581189bbfe7a3ff Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:27 +0200 Subject: [PATCH 084/299] reimplement: SHC_3BB0A8C1_0x00530310 100.00% Reimplemented --- .../triggerDeathAnimationForAllWildlife.cpp | 47 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/triggerDeathAnimationForAllWildlife.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/triggerDeathAnimationForAllWildlife.cpp b/src/OpenSHC/Map/Units/UnitsState/triggerDeathAnimationForAllWildlife.cpp new file mode 100644 index 000000000..caa89dd2e --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/triggerDeathAnimationForAllWildlife.cpp @@ -0,0 +1,47 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Game/GameMode.hpp" +#include "OpenSHC/Map/Units/States/UnitState.hpp" +#include "OpenSHC/Map/Units/UnitLogicState.hpp" +#include "OpenSHC/Map/Units/UnitType.hpp" + +#include "OpenSHC/Globals/DAT_GameSynchronyState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Game::GameMode; + using OpenSHC::Map::Units::UnitLogicState; + using OpenSHC::Map::Units::UnitType; + using OpenSHC::Map::Units::States::UnitState; + + // FUNCTION: STRONGHOLDCRUSADER 0x00530310 + void UnitsState::triggerDeathAnimationForAllWildlife() + { + if (DAT_GameSynchronyState::instance.currentGameMode == OpenSHC::Game::GM_SKIRMISH_SINGLE_PLAYER) { + return; + } + for (int unitID = 1; unitID < (int)this->maxUnitCount; ++unitID) { + if (this->units[unitID].logicalState != OpenSHC::Map::Units::ULS_NORMAL) { + continue; + } + if (this->units[unitID].dying != 0) { + continue; + } + if (this->units[unitID].owner != 0) { + continue; + } + if (this->units[unitID].unitType == OpenSHC::Map::Units::UT_ANTELOPESHDEER + || this->units[unitID].unitType == OpenSHC::Map::Units::UT_LIONSHWOLF + || this->units[unitID].unitType == OpenSHC::Map::Units::UT_CAMELSHBEAR + || this->units[unitID].unitType == OpenSHC::Map::Units::UT_RABBIT) { + this->units[unitID].state.generic = OpenSHC::Map::Units::States::US_STONE_DEATH_01; + this->units[unitID].animationCycleNumber = 0; + this->units[unitID].dying = 1; + } + } + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index bee611c9c..d5404ff2c 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -49373,7 +49373,7 @@ SHC_3BB0A8C1_0x00530240 | 100.0% | Reimplemented SHC_3BB0A8C1_0x005302B0 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x00530310 | 0.0% | Pending +SHC_3BB0A8C1_0x00530310 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00530390 | 100.0% | Reimplemented From b050166f35a20c4a320b7cf16780eee347d237e7 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:27 +0200 Subject: [PATCH 085/299] reimplement: SHC_3BB0A8C1_0x0053A4D0 100.00% Reimplemented --- .../findActiveSiegeEngineForTribe.cpp | 58 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/findActiveSiegeEngineForTribe.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/findActiveSiegeEngineForTribe.cpp b/src/OpenSHC/Map/Units/UnitsState/findActiveSiegeEngineForTribe.cpp new file mode 100644 index 000000000..354a5b996 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/findActiveSiegeEngineForTribe.cpp @@ -0,0 +1,58 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Map/Units/UnitLogicState.hpp" +#include "OpenSHC/Map/Units/UnitType.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Map::Units::UnitLogicState; + using OpenSHC::Map::Units::UnitType; + + // FUNCTION: STRONGHOLDCRUSADER 0x0053A4D0 + int UnitsState::findActiveSiegeEngineForTribe(int playerID) + { + for (int unitID = 1; unitID < (int)this->maxUnitCount; ++unitID) { + if (this->units[unitID].owner != playerID) { + continue; + } + if (this->units[unitID].logicalState != OpenSHC::Map::Units::ULS_NORMAL) { + continue; + } + if (this->units[unitID].dying != 0) { + continue; + } + if (this->units[unitID].isSelectable_OR_matchTime == 0) { + continue; + } + if (this->units[unitID].unitType == OpenSHC::Map::Units::UT_S_CATAPULT) { + return unitID; + } + if (this->units[unitID].unitType == OpenSHC::Map::Units::UT_S_TREBUCHET) { + return unitID; + } + if (this->units[unitID].unitType == OpenSHC::Map::Units::UT_S_MANGONEL) { + return unitID; + } + if (this->units[unitID].unitType == OpenSHC::Map::Units::UT_S_BALLISTA) { + return unitID; + } + if (this->units[unitID].unitType == OpenSHC::Map::Units::UT_S_FBALLISTA) { + return unitID; + } + if (this->units[unitID].unitType == OpenSHC::Map::Units::UT_S_BATTERINGRAM) { + return unitID; + } + if (this->units[unitID].unitType == OpenSHC::Map::Units::UT_S_TOWER) { + return unitID; + } + if (this->units[unitID].unitType == OpenSHC::Map::Units::UT_S_SHIELD) { + return unitID; + } + } + return 0; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index d5404ff2c..c4b2ce74b 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -59613,7 +59613,7 @@ SHC_3BB0A8C1_0x0053A4C0 | 0.0% | Pending SHC_3BB0A8C1_0x0053A4C1 | 0.0% | Pending -SHC_3BB0A8C1_0x0053A4D0 | 0.0% | Pending +SHC_3BB0A8C1_0x0053A4D0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0053A560 | 100.0% | Reimplemented From ddc092045ff9276ea04b35ec0546e8d9e0ded7a8 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:27 +0200 Subject: [PATCH 086/299] reimplement: SHC_3BB0A8C1_0x0052E7B0 100.00% Reimplemented --- .../Map/Units/UnitsState/clearAllUnits.cpp | 37 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/clearAllUnits.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/clearAllUnits.cpp b/src/OpenSHC/Map/Units/UnitsState/clearAllUnits.cpp new file mode 100644 index 000000000..3a95562f3 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/clearAllUnits.cpp @@ -0,0 +1,37 @@ +#include "OpenSHC/IO/LowLevelMemory.func.hpp" +#include "OpenSHC/Map/Units/UnitsState.func.hpp" + +#include "OpenSHC/Globals/DAT_LowLevelMemory.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + // FUNCTION: STRONGHOLDCRUSADER 0x0052E7B0 + void UnitsState::clearAllUnits() + { + this->unitCount = 0; + this->unknownInitially0_01 = 0; + this->totalUnitsInSelection = 0; + this->unitCountOfSelection[0] = 0; + this->unitCountOfSelection[1] = 0; + this->unitCountOfSelection[2] = 0; + this->unitCountOfSelection[3] = 0; + this->unitCountOfSelection[4] = 0; + this->unitCountOfSelection[5] = 0; + this->unitCountOfSelection[6] = 0; + this->unitCountOfSelection[7] = 0; + this->unitCountOfSelection[8] = 0; + for (int unitID = 0; unitID < 2500; ++unitID) { + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 1168, '\0', &this->units[unitID]); + } + this->maxUnitCount = 2500; + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 160800, '\0', DAT_TileMapState::instance.UnitLayer); + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index c4b2ce74b..292e5fe1e 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -49303,7 +49303,7 @@ SHC_3BB0A8C1_0x0052E120 | 0.0% | Pending SHC_3BB0A8C1_0x0052E1A0 | 0.0% | Pending -SHC_3BB0A8C1_0x0052E7B0 | 0.0% | Pending +SHC_3BB0A8C1_0x0052E7B0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0052E830 | 0.0% | Pending From 171c74478afcda48bbcfeb25e4d7ad205e07d207 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:28 +0200 Subject: [PATCH 087/299] reimplement: SHC_3BB0A8C1_0x00534030 55.77% switch shape differs --- .../Units/UnitsState/updateMicroPosition.cpp | 40 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/updateMicroPosition.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/updateMicroPosition.cpp b/src/OpenSHC/Map/Units/UnitsState/updateMicroPosition.cpp new file mode 100644 index 000000000..5dcc3ef88 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/updateMicroPosition.cpp @@ -0,0 +1,40 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" + +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_UnitPropertiesDefinedData.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + // FUNCTION: STRONGHOLDCRUSADER 0x00534030 + void UnitsState::updateMicroPosition(int unitID) + { + uint _microPartX = (byte)this->units[unitID].microXPosition & 7; + uint _microPartY = (byte)this->units[unitID].microYPosition & 7; + switch (DAT_TileMapState::instance.mapOrientation) { + case 0: + _microPartX = _microPartX * 2; + _microPartY = _microPartY << 4; + break; + case 2: + _microPartX = (7 - _microPartX) * 16; + _microPartY = _microPartY * 2; + break; + case 4: + _microPartX = (7 - _microPartX) * 2; + _microPartY = (7 - _microPartY) * 16; + break; + case 6: + _microPartY = (7 - _microPartY) * 2; + _microPartX = _microPartX << 4; + } + this->units[unitID].orientationRelatedPositionX + = (short)DAT_UnitPropertiesDefinedData::instance.field77_0x10f4c[0][_microPartX + _microPartY]; + this->units[unitID].orientationRelatedPositionY + = (short)DAT_UnitPropertiesDefinedData::instance.field77_0x10f4c[0][_microPartX + _microPartY + 1]; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 292e5fe1e..f6703a0fe 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -50781,7 +50781,7 @@ SHC_3BB0A8C1_0x00533F90 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00533FC0 | 70.8% | branch shape differs -SHC_3BB0A8C1_0x00534030 | 0.0% | Pending +SHC_3BB0A8C1_0x00534030 | 55.8% | switch shape differs SHC_3BB0A8C1_0x005340CC | 0.0% | Pending From 893e6f5af329eaf7d406ce229d7878f6cccb524f Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:28 +0200 Subject: [PATCH 088/299] reimplement: SHC_3BB0A8C1_0x0052FE00 84.85% reg alloc differs --- .../setFacingDirectionTowardUnitMicro.cpp | 40 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/setFacingDirectionTowardUnitMicro.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/setFacingDirectionTowardUnitMicro.cpp b/src/OpenSHC/Map/Units/UnitsState/setFacingDirectionTowardUnitMicro.cpp new file mode 100644 index 000000000..1e75ea082 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/setFacingDirectionTowardUnitMicro.cpp @@ -0,0 +1,40 @@ +#include "OpenSHC/Map/Navigation/DirectionAlgorithmState.func.hpp" +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Map/Units/UnitType.hpp" + +#include "OpenSHC/Globals/DAT_DirectionAlgorithmState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Map::Units::UnitType; + + // FUNCTION: STRONGHOLDCRUSADER 0x0052FE00 + void UnitsState::setFacingDirectionTowardUnitMicro(int unitID, int targetUnitID) + { + if (targetUnitID < 1) { + return; + } + MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::DirectionAlgorithmState_Func::calculatePreferredRelativeOrientation, + DAT_DirectionAlgorithmState::ptr)(this->units[unitID].microXPosition, + this->units[unitID].microYPosition, this->units[targetUnitID].microXPosition, + this->units[targetUnitID].microYPosition); + if (DAT_DirectionAlgorithmState::instance.orientation == 15) { + return; + } + UnitTypeShort _unitType = this->units[unitID].unitType; + this->units[unitID].orientation = (short)DAT_DirectionAlgorithmState::instance.orientation; + if (_unitType != OpenSHC::Map::Units::UT_E_KNIGHT) { + return; + } + this->units[unitID].orientation = this->units[unitID].orientation - 1; + if (this->units[unitID].orientation < 0) { + this->units[unitID].orientation = this->units[unitID].orientation + 8; + } + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index f6703a0fe..966cea3ff 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -49355,7 +49355,7 @@ SHC_3BB0A8C1_0x0052FCA0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0052FD00 | 0.0% | Pending -SHC_3BB0A8C1_0x0052FE00 | 0.0% | Pending +SHC_3BB0A8C1_0x0052FE00 | 84.8% | reg alloc differs SHC_3BB0A8C1_0x0052FE90 | 0.0% | Pending From b3481696980900e9e303825d8e0ac1261d003089 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:29 +0200 Subject: [PATCH 089/299] reimplement: SHC_3BB0A8C1_0x0053E790 36.36% orig uses global instance --- .../Map/Units/UnitsState/deleteUnit.cpp | 32 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/deleteUnit.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/deleteUnit.cpp b/src/OpenSHC/Map/Units/UnitsState/deleteUnit.cpp new file mode 100644 index 000000000..8f2e72764 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/deleteUnit.cpp @@ -0,0 +1,32 @@ +#include "OpenSHC/IO/LowLevelMemory.func.hpp" +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" +#include "OpenSHC/Map/Units/UnitsState.func.hpp" + +#include "OpenSHC/Globals/DAT_GameSynchronyState.hpp" +#include "OpenSHC/Globals/DAT_LowLevelMemory.hpp" +#include "OpenSHC/Globals/DAT_PathFindingState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + // FUNCTION: STRONGHOLDCRUSADER 0x0053E790 + void UnitsState::deleteUnit(uint unitID) + { + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::deselectUnit, this)(unitID); + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::clearOrDeselectUnitFromSelection, this)( + this->units[unitID].owner, unitID, 0); + if (DAT_GameSynchronyState::instance.currentPlayerFullIDArray[this->units[unitID].owner] == -1 + && this->units[unitID].isStalked == 0) { + MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::PathFindingState_Func::updateUnitDeathHeatmapIn3SpacesAroundTile, + DAT_PathFindingState::ptr)(this->units[unitID].x, this->units[unitID].y); + } + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::setupUnitSharingCurrentTilePosition, this)(unitID); + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 0x490, '\0', &this->units[unitID]); + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 966cea3ff..93f7367b1 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -60089,7 +60089,7 @@ SHC_3BB0A8C1_0x0053E440 | 0.0% | Pending SHC_3BB0A8C1_0x0053E6C0 | 0.0% | Pending -SHC_3BB0A8C1_0x0053E790 | 0.0% | Pending +SHC_3BB0A8C1_0x0053E790 | 36.4% | orig uses global instance SHC_3BB0A8C1_0x0053E820 | 100.0% | Reimplemented From 840ec37a12f06e9c7fdf74714ce41268afd6c38f Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:29 +0200 Subject: [PATCH 090/299] reimplement: SHC_3BB0A8C1_0x00536970 34.15% local loop var + reg alloc --- .../checkAnySelectedUnitCannotClimb.cpp | 42 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/checkAnySelectedUnitCannotClimb.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/checkAnySelectedUnitCannotClimb.cpp b/src/OpenSHC/Map/Units/UnitsState/checkAnySelectedUnitCannotClimb.cpp new file mode 100644 index 000000000..af067d379 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/checkAnySelectedUnitCannotClimb.cpp @@ -0,0 +1,42 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Map/Units/UnitLogicState.hpp" + +#include "OpenSHC/Globals/DAT_CurrentUnitSlotID.hpp" +#include "OpenSHC/Globals/DAT_GameSynchronyState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Map::Units::UnitLogicState; + + // FUNCTION: STRONGHOLDCRUSADER 0x00536970 + undefined4 UnitsState::checkAnySelectedUnitCannotClimb() + { + int _currentPlayerSlotID = DAT_GameSynchronyState::instance.currentPlayerSlotID; + for (DAT_CurrentUnitSlotID::instance = 1; (int)DAT_CurrentUnitSlotID::instance < (int)this->maxUnitCount; + DAT_CurrentUnitSlotID::instance = DAT_CurrentUnitSlotID::instance + 1) { + if (this->units[DAT_CurrentUnitSlotID::instance].logicalState != OpenSHC::Map::Units::ULS_NORMAL) { + continue; + } + if (this->units[DAT_CurrentUnitSlotID::instance].dying != 0) { + continue; + } + if (this->units[DAT_CurrentUnitSlotID::instance].isSelected == 0) { + continue; + } + if (this->units[DAT_CurrentUnitSlotID::instance].owner != _currentPlayerSlotID) { + return 0; + } + if (MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::checkUnitHasPropertyBasedOnUnitType, this)( + DAT_CurrentUnitSlotID::instance, 1) + == 0) { + return 0; + } + } + return 1; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 93f7367b1..216d1bb1f 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -51149,7 +51149,7 @@ SHC_3BB0A8C1_0x00536860 | 0.0% | Pending SHC_3BB0A8C1_0x005368D0 | 0.0% | Pending -SHC_3BB0A8C1_0x00536970 | 0.0% | Pending +SHC_3BB0A8C1_0x00536970 | 34.1% | local loop var + reg alloc SHC_3BB0A8C1_0x005369F0 | 80.0% | switch shape differs From 6e7cbd6fe68f7c0103bcb228b5f616d18d0d5568 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:29 +0200 Subject: [PATCH 091/299] reimplement: SHC_3BB0A8C1_0x00536CF0 52.17% branch order differs --- .../clearOrDeselectUnitFromSelection.cpp | 48 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/clearOrDeselectUnitFromSelection.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/clearOrDeselectUnitFromSelection.cpp b/src/OpenSHC/Map/Units/UnitsState/clearOrDeselectUnitFromSelection.cpp new file mode 100644 index 000000000..637e278a0 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/clearOrDeselectUnitFromSelection.cpp @@ -0,0 +1,48 @@ +#include "OpenSHC/Map/Units/TribesState.func.hpp" +#include "OpenSHC/Map/Units/UnitsState.func.hpp" + +#include "OpenSHC/Globals/DAT_CurrentUnitSlotID.hpp" +#include "OpenSHC/Globals/DAT_TribesState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + // FUNCTION: STRONGHOLDCRUSADER 0x00536CF0 + void UnitsState::clearOrDeselectUnitFromSelection(int playerID, uint unitID, int unitType) + { + if (unitID == 0xffffffff) { + MACRO_CALL_MEMBER(OpenSHC::Map::Units::TribesState_Func::clearTribesOfUnitType, DAT_TribesState::ptr)( + playerID, unitType); + return; + } + if (unitID == 0xfffffffe) { + MACRO_CALL_MEMBER(OpenSHC::Map::Units::TribesState_Func::clearTribesNotOfUnitType, + DAT_TribesState::ptr)(playerID, unitType); + return; + } + if (unitID == 0) { + this->unitCountOfSelection[playerID] = 0; + for (DAT_CurrentUnitSlotID::instance = 1; + (int)DAT_CurrentUnitSlotID::instance < (int)this->maxUnitCount; + DAT_CurrentUnitSlotID::instance = DAT_CurrentUnitSlotID::instance + 1) { + if (this->units[DAT_CurrentUnitSlotID::instance].owner == playerID) { + this->units[DAT_CurrentUnitSlotID::instance].ifSelectedThenPlayerID = 0; + } + } + return; + } + if (this->units[unitID].tribeID != 0) { + MACRO_CALL_MEMBER(OpenSHC::Map::Units::TribesState_Func::removeUnitFromTribe, DAT_TribesState::ptr)( + unitID, this->units[unitID].tribeID); + } + if (this->units[unitID].ifSelectedThenPlayerID == 0) { + return; + } + this->units[unitID].ifSelectedThenPlayerID = 0; + this->unitCountOfSelection[playerID] = this->unitCountOfSelection[playerID] - 1; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 216d1bb1f..d3dae0816 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -51209,7 +51209,7 @@ SHC_3BB0A8C1_0x00536C90 | 0.0% | Pending SHC_3BB0A8C1_0x00536CC0 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x00536CF0 | 0.0% | Pending +SHC_3BB0A8C1_0x00536CF0 | 52.2% | branch order differs SHC_3BB0A8C1_0x00536DA0 | 0.0% | Pending From 78e43567521692ab6c4e483f6f37d324ca78e4ef Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:30 +0200 Subject: [PATCH 092/299] reimplement: SHC_3BB0A8C1_0x00537A00 100.00% Reimplemented --- .../findNearestIdleCowForPlayer.cpp | 50 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/findNearestIdleCowForPlayer.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/findNearestIdleCowForPlayer.cpp b/src/OpenSHC/Map/Units/UnitsState/findNearestIdleCowForPlayer.cpp new file mode 100644 index 000000000..0d85327f4 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/findNearestIdleCowForPlayer.cpp @@ -0,0 +1,50 @@ +#include "OpenSHC/Map/Navigation/DirectionAlgorithmState.func.hpp" +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Map/Units/States/UnitState.hpp" +#include "OpenSHC/Map/Units/UnitLogicState.hpp" +#include "OpenSHC/Map/Units/UnitType.hpp" + +#include "OpenSHC/Globals/DAT_DirectionAlgorithmState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Map::Units::UnitLogicState; + using OpenSHC::Map::Units::UnitType; + using OpenSHC::Map::Units::States::UnitState; + + // FUNCTION: STRONGHOLDCRUSADER 0x00537A00 + int UnitsState::findNearestIdleCowForPlayer(int playerID, int x, int y) + { + int _bestDistance = 10000; + int _bestUnitID = 0; + for (int unitID = 1; unitID < (int)this->maxUnitCount; ++unitID) { + if (this->units[unitID].logicalState != OpenSHC::Map::Units::ULS_NORMAL) { + continue; + } + if (this->units[unitID].dying != 0) { + continue; + } + if (this->units[unitID].owner != playerID) { + continue; + } + if (this->units[unitID].unitType != OpenSHC::Map::Units::UT_COW) { + continue; + } + if (this->units[unitID].state.generic != OpenSHC::Map::Units::States::US_DETERMINE_NEXT_STATEUnk) { + continue; + } + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::DirectionAlgorithmState_Func::setAxisBasedDistanceResult, + DAT_DirectionAlgorithmState::ptr)(x, y, this->units[unitID].x, this->units[unitID].y); + if (DAT_DirectionAlgorithmState::instance.distanceHigh < _bestDistance) { + _bestDistance = DAT_DirectionAlgorithmState::instance.distanceHigh; + _bestUnitID = unitID; + } + } + return _bestUnitID; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index d3dae0816..76ca1a8f6 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -51247,7 +51247,7 @@ SHC_3BB0A8C1_0x005378D0 | 0.0% | Pending SHC_3BB0A8C1_0x005378F0 | 0.0% | Pending -SHC_3BB0A8C1_0x00537A00 | 0.0% | Pending +SHC_3BB0A8C1_0x00537A00 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00537AA0 | 0.0% | Pending From fc0380e0b6606c4bcb9f083f059556c2f1d742e5 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:30 +0200 Subject: [PATCH 093/299] reimplement: SHC_3BB0A8C1_0x0053CAE0 41.67% loop shape differs --- .../Units/UnitsState/getEnemyUnitIDNearby.cpp | 45 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/getEnemyUnitIDNearby.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/getEnemyUnitIDNearby.cpp b/src/OpenSHC/Map/Units/UnitsState/getEnemyUnitIDNearby.cpp new file mode 100644 index 000000000..7de828372 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/getEnemyUnitIDNearby.cpp @@ -0,0 +1,45 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +#include "OpenSHC/Globals/DAT_GameState.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x0053CAE0 + int UnitsState::getEnemyUnitIDNearby(int unitID, int tileUnk, int unitHeight) + { + int _otherUnitID = (short)DAT_TileMapState::instance.UnitLayer[tileUnk]; + if (_otherUnitID == 0) { + return 0; + } + for (int _visited = 0; _visited <= 1999; ++_visited) { + if (this->units[_otherUnitID].dying == 0 && this->units[_otherUnitID].unknownTestAgainst0_2 == 0 + && this->units[_otherUnitID].moveRelatedFlag != 1) { + int _otherHeight + = this->units[_otherUnitID].buildingHeight + this->units[_otherUnitID].terrainOrClimbHeight; + if (_otherHeight <= unitHeight + 0x20 && unitHeight + -0x20 <= _otherHeight + && MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::shouldUnitsEngageInMelee, this)( + unitID, _otherUnitID) + == FALSE + && (DAT_GameState::instance.mapAndTime.playerTeams[this->units[_otherUnitID].owner] + != DAT_GameState::instance.mapAndTime.playerTeams[this->units[unitID].owner] + || this->units[unitID].owner == 0)) { + return _otherUnitID; + } + } + _otherUnitID = (short)this->units[_otherUnitID].nextUnitOnTheSameTile; + if (_otherUnitID < 1) { + return 0; + } + } + return 0; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 76ca1a8f6..245c09c53 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -59671,7 +59671,7 @@ SHC_3BB0A8C1_0x0053C590 | 0.0% | Pending SHC_3BB0A8C1_0x0053CAC0 | 0.0% | Pending -SHC_3BB0A8C1_0x0053CAE0 | 0.0% | Pending +SHC_3BB0A8C1_0x0053CAE0 | 41.7% | loop shape differs SHC_3BB0A8C1_0x0053CBD0 | 0.0% | Pending From b07fdf18ba6d5f84ede05009bb710da5b5ce4a2a Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:31 +0200 Subject: [PATCH 094/299] reimplement: SHC_3BB0A8C1_0x00534520 17.39% orig unrolled, not a loop --- .../writeSixToTileMap1104InAllDirections.cpp | 26 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/writeSixToTileMap1104InAllDirections.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/writeSixToTileMap1104InAllDirections.cpp b/src/OpenSHC/Map/Units/UnitsState/writeSixToTileMap1104InAllDirections.cpp new file mode 100644 index 000000000..6eb72134b --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/writeSixToTileMap1104InAllDirections.cpp @@ -0,0 +1,26 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" + +#include "OpenSHC/Globals/DAT_TileMapState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + // FUNCTION: STRONGHOLDCRUSADER 0x00534520 + void UnitsState::writeSixToTileMap1104InAllDirections(int unitID, undefined4 six) + { + DAT_TileMapState::instance.SEC_TileMap1104[this->units[unitID].tile + 1] = (uchar)six; + DAT_TileMapState::instance.SEC_TileMap1104[this->units[unitID].tile - 1] = (uchar)six; + DAT_TileMapState::instance.SEC_TileMap1104[this->units[unitID].tile] = (uchar)six; + for (int row = 0; row < 8; row += 4) { + int _rowOffset = ((int*)DAT_TileMapState::instance + .ptr_MovementDirectionTranslationMatrix)[this->units[unitID].y * 8 + row]; + DAT_TileMapState::instance.SEC_TileMap1104[this->units[unitID].tile + _rowOffset - 1] = (uchar)six; + DAT_TileMapState::instance.SEC_TileMap1104[this->units[unitID].tile + _rowOffset + 1] = (uchar)six; + DAT_TileMapState::instance.SEC_TileMap1104[this->units[unitID].tile + _rowOffset] = (uchar)six; + } + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 245c09c53..7779c724a 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -50813,7 +50813,7 @@ SHC_3BB0A8C1_0x00534460 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00534490 | 0.0% | Pending -SHC_3BB0A8C1_0x00534520 | 0.0% | Pending +SHC_3BB0A8C1_0x00534520 | 17.4% | orig unrolled, not a loop SHC_3BB0A8C1_0x005345A0 | 0.0% | Pending From 3e93d84c8a173d219fdb1143fe4c084605ee0ec0 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:31 +0200 Subject: [PATCH 095/299] reimplement: SHC_3BB0A8C1_0x00534490 15.38% orig unrolled, 16-bit ORs --- .../stampOccupancyFlagOnSurroundingTiles.cpp | 31 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/stampOccupancyFlagOnSurroundingTiles.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/stampOccupancyFlagOnSurroundingTiles.cpp b/src/OpenSHC/Map/Units/UnitsState/stampOccupancyFlagOnSurroundingTiles.cpp new file mode 100644 index 000000000..bcf19808c --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/stampOccupancyFlagOnSurroundingTiles.cpp @@ -0,0 +1,31 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" + +#include "OpenSHC/Globals/DAT_TileMapState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + // FUNCTION: STRONGHOLDCRUSADER 0x00534490 + void UnitsState::stampOccupancyFlagOnSurroundingTiles(int unitID) + { + DAT_TileMapState::instance.OccupancyLayer[this->units[unitID].tile + 1] + |= this->units[unitID].occupancyOrFlag; + DAT_TileMapState::instance.OccupancyLayer[this->units[unitID].tile - 1] + |= this->units[unitID].occupancyOrFlag; + DAT_TileMapState::instance.OccupancyLayer[this->units[unitID].tile] |= this->units[unitID].occupancyOrFlag; + for (int row = 0; row < 8; row += 4) { + int _rowOffset = ((int*)DAT_TileMapState::instance + .ptr_MovementDirectionTranslationMatrix)[this->units[unitID].y * 8 + row]; + DAT_TileMapState::instance.OccupancyLayer[this->units[unitID].tile + _rowOffset - 1] + |= this->units[unitID].occupancyOrFlag; + DAT_TileMapState::instance.OccupancyLayer[this->units[unitID].tile + _rowOffset + 1] + |= this->units[unitID].occupancyOrFlag; + DAT_TileMapState::instance.OccupancyLayer[this->units[unitID].tile + _rowOffset] + |= this->units[unitID].occupancyOrFlag; + } + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 7779c724a..c2f8c4421 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -50811,7 +50811,7 @@ SHC_3BB0A8C1_0x005343F0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00534460 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x00534490 | 0.0% | Pending +SHC_3BB0A8C1_0x00534490 | 15.4% | orig unrolled, 16-bit ORs SHC_3BB0A8C1_0x00534520 | 17.4% | orig unrolled, not a loop From 6f63f4fcdd89142da6bf3306d6d1337d10b9bb52 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:31 +0200 Subject: [PATCH 096/299] reimplement: SHC_3BB0A8C1_0x00537EE0 100.00% Reimplemented --- .../UnitsState/setAIControlStatusTo100000.cpp | 41 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/setAIControlStatusTo100000.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/setAIControlStatusTo100000.cpp b/src/OpenSHC/Map/Units/UnitsState/setAIControlStatusTo100000.cpp new file mode 100644 index 000000000..a5b621c46 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/setAIControlStatusTo100000.cpp @@ -0,0 +1,41 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" + +#include "OpenSHC/Globals/DAT_GameState.hpp" +#include "OpenSHC/Globals/DAT_GameSynchronyState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + // FUNCTION: STRONGHOLDCRUSADER 0x00537EE0 + void UnitsState::setAIControlStatusTo100000() + { + if (DAT_GameSynchronyState::instance.currentPlayerFullIDArray[1] == -1) { + DAT_GameState::instance.playerDataArray[1].aiControlStatusRelated = 100000; + } + if (DAT_GameSynchronyState::instance.currentPlayerFullIDArray[2] == -1) { + DAT_GameState::instance.playerDataArray[2].aiControlStatusRelated = 100000; + } + if (DAT_GameSynchronyState::instance.currentPlayerFullIDArray[3] == -1) { + DAT_GameState::instance.playerDataArray[3].aiControlStatusRelated = 100000; + } + if (DAT_GameSynchronyState::instance.currentPlayerFullIDArray[4] == -1) { + DAT_GameState::instance.playerDataArray[4].aiControlStatusRelated = 100000; + } + if (DAT_GameSynchronyState::instance.currentPlayerFullIDArray[5] == -1) { + DAT_GameState::instance.playerDataArray[5].aiControlStatusRelated = 100000; + } + if (DAT_GameSynchronyState::instance.currentPlayerFullIDArray[6] == -1) { + DAT_GameState::instance.playerDataArray[6].aiControlStatusRelated = 100000; + } + if (DAT_GameSynchronyState::instance.currentPlayerFullIDArray[7] == -1) { + DAT_GameState::instance.playerDataArray[7].aiControlStatusRelated = 100000; + } + if (DAT_GameSynchronyState::instance.currentPlayerFullIDArray[8] == -1) { + DAT_GameState::instance.playerDataArray[8].aiControlStatusRelated = 100000; + } + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index c2f8c4421..aff9d75ae 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -51261,7 +51261,7 @@ SHC_3BB0A8C1_0x00537D60 | 0.0% | Pending SHC_3BB0A8C1_0x00537E00 | 0.0% | Pending -SHC_3BB0A8C1_0x00537EE0 | 0.0% | Pending +SHC_3BB0A8C1_0x00537EE0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00537F60 | 0.0% | Pending From aaf4ee31e2a8c72743313834801f8ef191d7fcd3 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:32 +0200 Subject: [PATCH 097/299] reimplement: SHC_3BB0A8C1_0x005334A0 41.24% orig caches unitType local --- .../getRemainingRequiredEngineers.cpp | 52 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/getRemainingRequiredEngineers.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/getRemainingRequiredEngineers.cpp b/src/OpenSHC/Map/Units/UnitsState/getRemainingRequiredEngineers.cpp new file mode 100644 index 000000000..320041008 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/getRemainingRequiredEngineers.cpp @@ -0,0 +1,52 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Map/Units/UnitType.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Map::Units::UnitType; + + // FUNCTION: STRONGHOLDCRUSADER 0x005334A0 + int UnitsState::getRemainingRequiredEngineers(int unitID) + { + if (this->units[unitID].unitType == OpenSHC::Map::Units::UT_S_TREBUCHET) { + return 3 - this->units[unitID].digTileX__OR__countCurrentlyManningEnginers__OR__forCowsRandomBelow300; + } + if (this->units[unitID].unitType != OpenSHC::Map::Units::UT_S_CATAPULT) { + if (this->units[unitID].unitType == OpenSHC::Map::Units::UT_S_TOWER) { + return 4 + - this->units[unitID].digTileX__OR__countCurrentlyManningEnginers__OR__forCowsRandomBelow300; + } + if (this->units[unitID].unitType == OpenSHC::Map::Units::UT_S_BATTERINGRAM) { + return 4 + - this->units[unitID].digTileX__OR__countCurrentlyManningEnginers__OR__forCowsRandomBelow300; + } + if (this->units[unitID].unitType == OpenSHC::Map::Units::UT_S_SHIELD) { + return 1 + - this->units[unitID].digTileX__OR__countCurrentlyManningEnginers__OR__forCowsRandomBelow300; + } + if (this->units[unitID].unitType != OpenSHC::Map::Units::UT_S_MANGONEL) { + if (this->units[unitID].unitType == OpenSHC::Map::Units::UT_S_BALLISTA) { + return 2 + - this->units[unitID] + .digTileX__OR__countCurrentlyManningEnginers__OR__forCowsRandomBelow300; + } + if (this->units[unitID].unitType != OpenSHC::Map::Units::UT_S_FBALLISTA) { + if (this->units[unitID].unitType != OpenSHC::Map::Units::UT_S_SIEGETENT) { + return 0; + } + if ((this->units[unitID].fixedRng & 2) != 0) { + return 3 + - this->units[unitID] + .digTileX__OR__countCurrentlyManningEnginers__OR__forCowsRandomBelow300; + } + } + } + } + return 2 - this->units[unitID].digTileX__OR__countCurrentlyManningEnginers__OR__forCowsRandomBelow300; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index aff9d75ae..e5354867d 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -50669,7 +50669,7 @@ SHC_3BB0A8C1_0x0053348C | 0.0% | Pending SHC_3BB0A8C1_0x00533490 | 0.0% | Pending -SHC_3BB0A8C1_0x005334A0 | 0.0% | Pending +SHC_3BB0A8C1_0x005334A0 | 41.2% | orig caches unitType local SHC_3BB0A8C1_0x00533580 | 0.0% | Pending From 636c60d7593b556a8a32ed5cc7157361d52a5db3 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:32 +0200 Subject: [PATCH 098/299] reimplement: SHC_3BB0A8C1_0x0053D850 69.77% reg alloc differs --- .../resumeMovementAfterInterruption.cpp | 44 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/resumeMovementAfterInterruption.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/resumeMovementAfterInterruption.cpp b/src/OpenSHC/Map/Units/UnitsState/resumeMovementAfterInterruption.cpp new file mode 100644 index 000000000..38299840d --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/resumeMovementAfterInterruption.cpp @@ -0,0 +1,44 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Map/Units/States/UnitState.hpp" +#include "OpenSHC/Map/Units/UnitLogicState.hpp" +#include "OpenSHC/Map/Units/UnitType.hpp" + +#include "OpenSHC/Globals/DAT_CurrentUnitSlotID.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Map::Units::UnitLogicState; + using OpenSHC::Map::Units::UnitType; + using OpenSHC::Map::Units::States::UnitState; + + // FUNCTION: STRONGHOLDCRUSADER 0x0053D850 + void UnitsState::resumeMovementAfterInterruption(int unitID) + { + if (this->units[unitID].dying != 0) { + return; + } + if (this->units[unitID].logicalState == OpenSHC::Map::Units::ULS_REMOVE) { + return; + } + short _destinationY = this->units[unitID].destinationY_2Unk; + short _destinationX = this->units[unitID].destinationX_2Unk; + this->units[unitID].state = this->units[unitID].state_3; + this->units[unitID].tunnelerFinishedDigging = 0; + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::setDestinationForUnit, this)( + unitID, _destinationX, _destinationY, 0); + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::changeDestinationByLeftover, this)(unitID); + if (this->units[unitID].unitType != OpenSHC::Map::Units::UT_LIONSHWOLF + && this->units[unitID].unitType != OpenSHC::Map::Units::UT_CAGEDOG) { + return; + } + this->units[DAT_CurrentUnitSlotID::instance].state.generic + = OpenSHC::Map::Units::States::US_MOVE_TO_DESTINATION; + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::makeUnitStopWalkingByClearingPathProgressState, + this)(DAT_CurrentUnitSlotID::instance); + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index e5354867d..3ee865273 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -60015,7 +60015,7 @@ SHC_3BB0A8C1_0x0053D3C2 | 0.0% | Pending SHC_3BB0A8C1_0x0053D3D0 | 0.0% | Pending -SHC_3BB0A8C1_0x0053D850 | 0.0% | Pending +SHC_3BB0A8C1_0x0053D850 | 69.8% | reg alloc differs SHC_3BB0A8C1_0x0053D900 | 0.0% | Pending From 0b68652205582e74fb7aa6c9497abcbb3eba4d3b Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:33 +0200 Subject: [PATCH 099/299] reimplement: SHC_3BB0A8C1_0x00537D60 14.63% orig uses global instance --- .../Map/Units/UnitsState/tryAttackUnitID.cpp | 50 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/tryAttackUnitID.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/tryAttackUnitID.cpp b/src/OpenSHC/Map/Units/UnitsState/tryAttackUnitID.cpp new file mode 100644 index 000000000..f4932e4b2 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/tryAttackUnitID.cpp @@ -0,0 +1,50 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Map/Units/Pathfinding/DestinationNeededEnum.hpp" +#include "OpenSHC/Map/Units/States/UnitState.hpp" +#include "OpenSHC/Map/Units/UnitLogicState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Map::Units::UnitLogicState; + using OpenSHC::Map::Units::Pathfinding::DestinationNeededEnum; + using OpenSHC::Map::Units::States::UnitState; + + // FUNCTION: STRONGHOLDCRUSADER 0x00537D60 + undefined4 UnitsState::tryAttackUnitID(int unitID_1, int unitID_2) + { + if (unitID_2 < 1) { + return 0; + } + if (this->units[unitID_1].logicalState != OpenSHC::Map::Units::ULS_NORMAL) { + return 0; + } + if (this->units[unitID_1].dying != 0) { + return 0; + } + if (this->units[unitID_2].logicalState != OpenSHC::Map::Units::ULS_NORMAL) { + return 0; + } + if (this->units[unitID_2].dying != 0) { + return 0; + } + if (this->units[unitID_1].state.generic == (UnitState)0xcf) { + return 0; + } + if (this->units[unitID_1].state.generic == OpenSHC::Map::Units::States::US_MELEE_ATTACK) { + return 0; + } + this->units[unitID_1].movementType_OR_targetUnitID = (short)unitID_2; + this->units[unitID_1].targetedUnitID__OR__engineerMannedSiegeEngineRef = (short)unitID_2; + this->units[unitID_1].targetedUnitUIDUnk_OR_someAppearTileUnk_OR_buildingUID_OR_pitchDitchUID_OR_entityUID + = this->units[unitID_2].uid; + this->units[unitID_2].huntedBy = this->units[unitID_2].huntedBy + 1; + this->units[unitID_1].state.generic = (UnitState)0xcf; + this->units[unitID_1].destinationNeeded = OpenSHC::Map::Units::Pathfinding::DNE_DESTINATION_NEEDED; + return 1; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 3ee865273..7af0284b8 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -51257,7 +51257,7 @@ SHC_3BB0A8C1_0x00537C10 | 0.0% | Pending SHC_3BB0A8C1_0x00537C90 | 0.0% | Pending -SHC_3BB0A8C1_0x00537D60 | 0.0% | Pending +SHC_3BB0A8C1_0x00537D60 | 14.6% | orig uses global instance SHC_3BB0A8C1_0x00537E00 | 0.0% | Pending From 1e5bca9f2ac395bab6caf130450032a00bb21020 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:33 +0200 Subject: [PATCH 100/299] reimplement: SHC_3BB0A8C1_0x00536370 77.27% cond order differs --- .../getMaxStoneAmmoInSelectedSiegeEngines.cpp | 47 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/getMaxStoneAmmoInSelectedSiegeEngines.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/getMaxStoneAmmoInSelectedSiegeEngines.cpp b/src/OpenSHC/Map/Units/UnitsState/getMaxStoneAmmoInSelectedSiegeEngines.cpp new file mode 100644 index 000000000..879680040 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/getMaxStoneAmmoInSelectedSiegeEngines.cpp @@ -0,0 +1,47 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Map/Units/UnitLogicState.hpp" +#include "OpenSHC/Map/Units/UnitType.hpp" + +#include "OpenSHC/Globals/DAT_CurrentUnitSlotID.hpp" +#include "OpenSHC/Globals/DAT_GameSynchronyState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Map::Units::UnitLogicState; + using OpenSHC::Map::Units::UnitType; + + // FUNCTION: STRONGHOLDCRUSADER 0x00536370 + int UnitsState::getMaxStoneAmmoInSelectedSiegeEngines() + { + int _maxStoneAmmunition = 0; + for (DAT_CurrentUnitSlotID::instance = 1; (int)DAT_CurrentUnitSlotID::instance < (int)this->maxUnitCount; + DAT_CurrentUnitSlotID::instance = DAT_CurrentUnitSlotID::instance + 1) { + if (this->units[DAT_CurrentUnitSlotID::instance].logicalState != OpenSHC::Map::Units::ULS_NORMAL) { + continue; + } + if (this->units[DAT_CurrentUnitSlotID::instance].dying != 0) { + continue; + } + if (this->units[DAT_CurrentUnitSlotID::instance].isSelected == 0) { + continue; + } + if (this->units[DAT_CurrentUnitSlotID::instance].owner + != DAT_GameSynchronyState::instance.currentPlayerSlotID) { + return 0; + } + if (this->units[DAT_CurrentUnitSlotID::instance].unitType != OpenSHC::Map::Units::UT_S_CATAPULT + && this->units[DAT_CurrentUnitSlotID::instance].unitType != OpenSHC::Map::Units::UT_S_TREBUCHET) { + continue; + } + if (_maxStoneAmmunition < this->units[DAT_CurrentUnitSlotID::instance].stoneAmmunition) { + _maxStoneAmmunition = this->units[DAT_CurrentUnitSlotID::instance].stoneAmmunition; + } + } + return _maxStoneAmmunition; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 7af0284b8..be94a7332 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -51123,7 +51123,7 @@ SHC_3BB0A8C1_0x005362F0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00536310 | 0.0% | Pending -SHC_3BB0A8C1_0x00536370 | 0.0% | Pending +SHC_3BB0A8C1_0x00536370 | 77.3% | cond order differs SHC_3BB0A8C1_0x00536400 | 0.0% | Pending From 63df6636707b1ad7831be7c9ee0c985de040e499 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:33 +0200 Subject: [PATCH 101/299] reimplement: SHC_3BB0A8C1_0x00535FD0 88.89% orig walks hotkey ptr --- .../makeSelectionBasedOnShortcut.cpp | 45 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/makeSelectionBasedOnShortcut.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/makeSelectionBasedOnShortcut.cpp b/src/OpenSHC/Map/Units/UnitsState/makeSelectionBasedOnShortcut.cpp new file mode 100644 index 000000000..828dd5c97 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/makeSelectionBasedOnShortcut.cpp @@ -0,0 +1,45 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Map/Units/UnitLogicState.hpp" + +#include "OpenSHC/Globals/DAT_CurrentUnitSlotID.hpp" +#include "OpenSHC/Globals/DAT_GameState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Map::Units::UnitLogicState; + + // FUNCTION: STRONGHOLDCRUSADER 0x00535FD0 + void UnitsState::makeSelectionBasedOnShortcut(int section1099ID) + { + for (DAT_CurrentUnitSlotID::instance = 1; (int)DAT_CurrentUnitSlotID::instance < (int)this->maxUnitCount; + DAT_CurrentUnitSlotID::instance = DAT_CurrentUnitSlotID::instance + 1) { + if (this->units[DAT_CurrentUnitSlotID::instance].logicalState == OpenSHC::Map::Units::ULS_NORMAL + && this->units[DAT_CurrentUnitSlotID::instance].dying == 0) { + this->units[DAT_CurrentUnitSlotID::instance].isSelected = 0; + } + } + this->totalUnitsInSelection = 0; + for (int i = 0; i < 2500; ++i) { + int _unitID = DAT_GameState::instance.hotkeyTribes[section1099ID].units[i].id; + if (_unitID == -1) { + continue; + } + if (this->units[_unitID].uid == DAT_GameState::instance.hotkeyTribes[section1099ID].units[i].uid + && this->units[_unitID].unknownTestAgainst0_2 == 0 + && this->units[_unitID].disappearFadeAlphaCountdown == 0) { + this->units[_unitID].isSelected = 1; + this->totalUnitsInSelection = this->totalUnitsInSelection + 1; + } else { + DAT_GameState::instance.hotkeyTribes[section1099ID].units[i].id = -1; + } + } + if (this->totalUnitsInSelection > 0) { + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::createTribeFromSelectedUnits, this)(); + } + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index be94a7332..52db3b779 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -51107,7 +51107,7 @@ SHC_3BB0A8C1_0x00535DF0 | 46.1% | call+reg alloc differs SHC_3BB0A8C1_0x00535E20 | 0.0% | Pending -SHC_3BB0A8C1_0x00535FD0 | 0.0% | Pending +SHC_3BB0A8C1_0x00535FD0 | 88.9% | orig walks hotkey ptr SHC_3BB0A8C1_0x005360A0 | 0.0% | Pending From 04cd64eed2e63483c6b68aab7676ceac58accbed Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:34 +0200 Subject: [PATCH 102/299] reimplement: SHC_3BB0A8C1_0x00533580 24.49% orig caches locals --- .../checkTargetBuildingPossibilityOrState.cpp | 44 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/checkTargetBuildingPossibilityOrState.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/checkTargetBuildingPossibilityOrState.cpp b/src/OpenSHC/Map/Units/UnitsState/checkTargetBuildingPossibilityOrState.cpp new file mode 100644 index 000000000..eec44b3c8 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/checkTargetBuildingPossibilityOrState.cpp @@ -0,0 +1,44 @@ +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Map/Units/UnitInstructionType.hpp" +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_CurrentUnitSlotID.hpp" +#include "OpenSHC/Globals/DAT_GameState.hpp" +#include "OpenSHC/Globals/DAT_PathFindingState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Map::Units::UnitInstructionType; + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x00533580 + BOOLEnum UnitsState::checkTargetBuildingPossibilityOrState(int unitID) + { + int _playerID = this->units[unitID].owner; + if (DAT_GameState::instance.playerDataArray[_playerID].totalEnemyUnitsCount > 0) { + return TRUE; + } + if (this->units[unitID].targetingType == OpenSHC::Map::Units::UIT_ATTACK_BUILDING) { + return ( + BOOLEnum)(DAT_BuildingsState::instance.buildings[this->units[unitID].targetID_OR_targetBuildingID] + .uid + == this->units[DAT_CurrentUnitSlotID::instance] + .targetedUnitUIDUnk_OR_someAppearTileUnk_OR_buildingUID_OR_pitchDitchUID_OR_entityUID); + } + int _shootTargetMicroX = this->units[unitID].shootTargetMicroX; + int _shootTargetMicroY = this->units[unitID].shootTargetMicroY; + return (BOOLEnum)(MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func:: + checkEnemyBuildingOrDefensiveStructureWithin12Tiles, + DAT_PathFindingState::ptr)(_playerID, + (_shootTargetMicroX + (_shootTargetMicroX >> 0x1f & 7U)) >> 3, + (_shootTargetMicroY + (_shootTargetMicroY >> 0x1f & 7U)) >> 3) + != FALSE); + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 52db3b779..34484dc7e 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -50671,7 +50671,7 @@ SHC_3BB0A8C1_0x00533490 | 0.0% | Pending SHC_3BB0A8C1_0x005334A0 | 41.2% | orig caches unitType local -SHC_3BB0A8C1_0x00533580 | 0.0% | Pending +SHC_3BB0A8C1_0x00533580 | 24.5% | orig caches locals SHC_3BB0A8C1_0x00533630 | 0.0% | Pending From 1dbede23a4b599b317ce151d278a51281903c820 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:34 +0200 Subject: [PATCH 103/299] reimplement: SHC_3BB0A8C1_0x00533810 80.26% orig walks matrix row ptr --- .../findAndDestroyAdjacentEnemyLadder.cpp | 44 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/findAndDestroyAdjacentEnemyLadder.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/findAndDestroyAdjacentEnemyLadder.cpp b/src/OpenSHC/Map/Units/UnitsState/findAndDestroyAdjacentEnemyLadder.cpp new file mode 100644 index 000000000..07f68ac22 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/findAndDestroyAdjacentEnemyLadder.cpp @@ -0,0 +1,44 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Map/Units/States/UnitState.hpp" +#include "OpenSHC/Map/Units/UnitType.hpp" + +#include "OpenSHC/Globals/DAT_GameState.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Map::Units::UnitType; + using OpenSHC::Map::Units::States::UnitState; + + // FUNCTION: STRONGHOLDCRUSADER 0x00533810 + int UnitsState::findAndDestroyAdjacentEnemyLadder(int unitID, int checkOnly) + { + for (int direction = 0; direction < 8; ++direction) { + for (int _otherUnitID = (short)DAT_TileMapState::instance.UnitLayer + [DAT_TileMapState::instance.directionTranslationMatrix[this->units[unitID].y][direction] + + this->units[unitID].tile]; + _otherUnitID > 0; _otherUnitID = (short)this->units[_otherUnitID].nextUnitOnTheSameTile) { + if (DAT_GameState::instance.mapAndTime.playerTeams[this->units[unitID].owner] + != DAT_GameState::instance.mapAndTime.playerTeams[this->units[_otherUnitID].owner] + && this->units[unitID].owner != 0 + && this->units[_otherUnitID].unitType == OpenSHC::Map::Units::UT_E_LADDER + && this->units[_otherUnitID].state.generic == (UnitState)3) { + if (checkOnly != 0) { + return direction; + } + this->units[_otherUnitID].dying = 1; + this->units[_otherUnitID].animationCycleNumber = 0; + this->units[_otherUnitID].state.generic = OpenSHC::Map::Units::States::US_DEATH_02; + this->units[_otherUnitID].tunnelerFinishedDigging = 1; + return 1; + } + } + } + return -1; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 34484dc7e..bd793d50a 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -50675,7 +50675,7 @@ SHC_3BB0A8C1_0x00533580 | 24.5% | orig caches locals SHC_3BB0A8C1_0x00533630 | 0.0% | Pending -SHC_3BB0A8C1_0x00533810 | 0.0% | Pending +SHC_3BB0A8C1_0x00533810 | 80.3% | orig walks matrix row ptr SHC_3BB0A8C1_0x00533920 | 100.0% | Reimplemented From 09db8e1fa4ff70fef7879a02f21d5047688b7749 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:34 +0200 Subject: [PATCH 104/299] reimplement: SHC_3BB0A8C1_0x00536690 92.11% Style pass, asm differs --- .../getFirstSelectedSiegeEngineID.cpp | 54 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/getFirstSelectedSiegeEngineID.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/getFirstSelectedSiegeEngineID.cpp b/src/OpenSHC/Map/Units/UnitsState/getFirstSelectedSiegeEngineID.cpp new file mode 100644 index 000000000..75b4758a4 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/getFirstSelectedSiegeEngineID.cpp @@ -0,0 +1,54 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Map/Units/UnitLogicState.hpp" +#include "OpenSHC/Map/Units/UnitType.hpp" + +#include "OpenSHC/Globals/DAT_CurrentUnitSlotID.hpp" +#include "OpenSHC/Globals/DAT_GameSynchronyState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Map::Units::UnitLogicState; + using OpenSHC::Map::Units::UnitType; + + // FUNCTION: STRONGHOLDCRUSADER 0x00536690 + uint UnitsState::getFirstSelectedSiegeEngineID() + { + for (DAT_CurrentUnitSlotID::instance = 1; (int)DAT_CurrentUnitSlotID::instance < (int)this->maxUnitCount; + DAT_CurrentUnitSlotID::instance = DAT_CurrentUnitSlotID::instance + 1) { + if (this->units[DAT_CurrentUnitSlotID::instance].logicalState != OpenSHC::Map::Units::ULS_NORMAL) { + continue; + } + if (this->units[DAT_CurrentUnitSlotID::instance].dying != 0) { + continue; + } + if (this->units[DAT_CurrentUnitSlotID::instance].isSelected == 0) { + continue; + } + if (this->units[DAT_CurrentUnitSlotID::instance].owner + != DAT_GameSynchronyState::instance.currentPlayerSlotID) { + return 0; + } + if (this->units[DAT_CurrentUnitSlotID::instance].unitType == OpenSHC::Map::Units::UT_S_CATAPULT) { + return DAT_CurrentUnitSlotID::instance; + } + if (this->units[DAT_CurrentUnitSlotID::instance].unitType == OpenSHC::Map::Units::UT_S_TREBUCHET) { + return DAT_CurrentUnitSlotID::instance; + } + if (this->units[DAT_CurrentUnitSlotID::instance].unitType == OpenSHC::Map::Units::UT_S_MANGONEL) { + return DAT_CurrentUnitSlotID::instance; + } + if (this->units[DAT_CurrentUnitSlotID::instance].unitType == OpenSHC::Map::Units::UT_S_BALLISTA) { + return DAT_CurrentUnitSlotID::instance; + } + if (this->units[DAT_CurrentUnitSlotID::instance].unitType == OpenSHC::Map::Units::UT_S_FBALLISTA) { + return DAT_CurrentUnitSlotID::instance; + } + } + return 0; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index bd793d50a..de71aee83 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -51139,7 +51139,7 @@ SHC_3BB0A8C1_0x00536610 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00536630 | 0.0% | Pending -SHC_3BB0A8C1_0x00536690 | 0.0% | Pending +SHC_3BB0A8C1_0x00536690 | 92.1% | Style pass, asm differs SHC_3BB0A8C1_0x00536710 | 100.0% | Reimplemented From 3423386cb195150b34d37d4eef2955028ae95382 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:35 +0200 Subject: [PATCH 105/299] reimplement: SHC_3BB0A8C1_0x00535680 23.68% guard order differs --- .../getSelectedEngineerCarryingResource.cpp | 50 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/getSelectedEngineerCarryingResource.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/getSelectedEngineerCarryingResource.cpp b/src/OpenSHC/Map/Units/UnitsState/getSelectedEngineerCarryingResource.cpp new file mode 100644 index 000000000..4401ef9c6 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/getSelectedEngineerCarryingResource.cpp @@ -0,0 +1,50 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Map/Units/UnitLogicState.hpp" +#include "OpenSHC/Map/Units/UnitType.hpp" +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +#include "OpenSHC/Globals/DAT_CurrentUnitSlotID.hpp" +#include "OpenSHC/Globals/DAT_GameSynchronyState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Map::Units::UnitLogicState; + using OpenSHC::Map::Units::UnitType; + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x00535680 + uint UnitsState::getSelectedEngineerCarryingResource() + { + /* Does not dirty EDX. -TheRedDaemon */ + if (MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::selectionContainsEngineersOnly, this)() + == FALSE) { + return 0; + } + for (DAT_CurrentUnitSlotID::instance = 1; (int)DAT_CurrentUnitSlotID::instance < (int)this->maxUnitCount; + DAT_CurrentUnitSlotID::instance = DAT_CurrentUnitSlotID::instance + 1) { + if (this->units[DAT_CurrentUnitSlotID::instance].logicalState != OpenSHC::Map::Units::ULS_NORMAL) { + continue; + } + if (this->units[DAT_CurrentUnitSlotID::instance].dying != 0) { + continue; + } + if (this->units[DAT_CurrentUnitSlotID::instance].isSelected == 0) { + continue; + } + if (this->units[DAT_CurrentUnitSlotID::instance].owner + != DAT_GameSynchronyState::instance.currentPlayerSlotID) { + return 0; + } + if (this->units[DAT_CurrentUnitSlotID::instance].unitType == OpenSHC::Map::Units::UT_E_ENGINEER + && this->units[DAT_CurrentUnitSlotID::instance].resourceToDeposit != 0) { + return DAT_CurrentUnitSlotID::instance; + } + } + return 0; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index de71aee83..2a668e3f3 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -51075,7 +51075,7 @@ SHC_3BB0A8C1_0x00535580 | 100.0% | Reimplemented SHC_3BB0A8C1_0x005355E0 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x00535680 | 0.0% | Pending +SHC_3BB0A8C1_0x00535680 | 23.7% | guard order differs SHC_3BB0A8C1_0x00535700 | 100.0% | Reimplemented From cb5adc0d15eabe4cb4ea1413e8e7f27594bc6e7b Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:35 +0200 Subject: [PATCH 106/299] reimplement: SHC_3BB0A8C1_0x00530650 80.36% reg alloc differs --- ...keUnitsDisappearThatCannotReachTheKeep.cpp | 55 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/makeUnitsDisappearThatCannotReachTheKeep.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/makeUnitsDisappearThatCannotReachTheKeep.cpp b/src/OpenSHC/Map/Units/UnitsState/makeUnitsDisappearThatCannotReachTheKeep.cpp new file mode 100644 index 000000000..98dd92ca9 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/makeUnitsDisappearThatCannotReachTheKeep.cpp @@ -0,0 +1,55 @@ +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Map/Units/States/UnitState.hpp" +#include "OpenSHC/Map/Units/UnitLogicState.hpp" + +#include "OpenSHC/Globals/DAT_GameState.hpp" +#include "OpenSHC/Globals/DAT_PathFindingState.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Map::Units::UnitLogicState; + using OpenSHC::Map::Units::States::UnitState; + + // FUNCTION: STRONGHOLDCRUSADER 0x00530650 + void UnitsState::makeUnitsDisappearThatCannotReachTheKeep(int playerID) + { + ushort _areaOfKeep + = DAT_TileMapState::instance + .PathConnectionLayer[DAT_GameState::instance.playerDataArray[playerID].campground.tileEntry]; + for (int unitID = 1; unitID < (int)this->maxUnitCount; ++unitID) { + if (this->units[unitID].owner != playerID) { + continue; + } + if (this->units[unitID].logicalState != OpenSHC::Map::Units::ULS_NORMAL) { + continue; + } + if (this->units[unitID].isSelectable_OR_matchTime != 0) { + continue; + } + if (this->units[unitID].dying != 0) { + continue; + } + if (this->units[unitID].isStalked != 0) { + continue; + } + if (MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::PathFindingState_Func::calculateCanPlayerUnitsNavigateToAreaFromArea, + DAT_PathFindingState::ptr)(playerID, (short)_areaOfKeep, + (short)DAT_TileMapState::instance.PathConnectionLayer[this->units[unitID].tile], 0) + != 0) { + continue; + } + this->units[unitID].state.generic = OpenSHC::Map::Units::States::US_DISAPPEAR; + this->units[unitID].animationCycleNumber = 0; + this->units[unitID].disappearFadeAlphaCountdown = 0; + this->units[unitID].dying = 1; + } + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 2a668e3f3..9aa52b316 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -49623,7 +49623,7 @@ SHC_3BB0A8C1_0x00530648 | 0.0% | Pending SHC_3BB0A8C1_0x00530649 | 0.0% | Pending -SHC_3BB0A8C1_0x00530650 | 0.0% | Pending +SHC_3BB0A8C1_0x00530650 | 80.4% | reg alloc differs SHC_3BB0A8C1_0x00530690 | 0.0% | Pending From 4c96b540d9e03818e639cb80870a568fc84f2e15 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:36 +0200 Subject: [PATCH 107/299] reimplement: SHC_3BB0A8C1_0x0052F730 45.36% branch shape differs --- ...itsSameTileLinkageIfNoLongerApplicable.cpp | 45 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/removeUnitsSameTileLinkageIfNoLongerApplicable.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/removeUnitsSameTileLinkageIfNoLongerApplicable.cpp b/src/OpenSHC/Map/Units/UnitsState/removeUnitsSameTileLinkageIfNoLongerApplicable.cpp new file mode 100644 index 000000000..2fc4c0a5a --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/removeUnitsSameTileLinkageIfNoLongerApplicable.cpp @@ -0,0 +1,45 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" + +#include "OpenSHC/Globals/DAT_GameState.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + // FUNCTION: STRONGHOLDCRUSADER 0x0052F730 + void UnitsState::removeUnitsSameTileLinkageIfNoLongerApplicable() + { + if (DAT_GameState::instance.mapAndTime.multiplayerUnitSameTileLinkageTimeWindow < 1) { + DAT_GameState::instance.mapAndTime.multiplayerUnitSameTileLinkageTimeWindow = 0; + return; + } + if (DAT_GameState::instance.mapAndTime.multiplayerUnitSameTileLinkageTimeWindow < 100) { + DAT_GameState::instance.mapAndTime.multiplayerUnitSameTileLinkageTimeWindow + = DAT_GameState::instance.mapAndTime.multiplayerUnitSameTileLinkageTimeWindow + 1; + if (DAT_GameState::instance.mapAndTime.multiplayerUnitSameTileLinkageTimeWindow > 50) { + DAT_GameState::instance.mapAndTime.multiplayerUnitSameTileLinkageTimeWindow = 0; + } + return; + } + DAT_GameState::instance.mapAndTime.multiplayerUnitSameTileLinkageTimeWindow = 0; + for (int tile = 0; tile < 0x13a10; ++tile) { + if ((short)DAT_TileMapState::instance.UnitLayer[tile] < 0 + || (short)DAT_TileMapState::instance.UnitLayer[tile] > 2500) { + DAT_TileMapState::instance.UnitLayer[tile] = 0; + continue; + } + for (int unitID = (short)DAT_TileMapState::instance.UnitLayer[tile]; unitID != 0; + unitID = (short)this->units[unitID].nextUnitOnTheSameTile) { + if (this->units[unitID].tile != tile && this->units[unitID].usingTeleport == 0 + && this->units[unitID].field303_0x413 == 0) { + DAT_TileMapState::instance.UnitLayer[tile] = this->units[unitID].nextUnitOnTheSameTile; + break; + } + } + } + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 9aa52b316..6ebfd04ae 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -49341,7 +49341,7 @@ SHC_3BB0A8C1_0x0052F680 | 0.0% | Pending SHC_3BB0A8C1_0x0052F6C0 | 0.0% | Pending -SHC_3BB0A8C1_0x0052F730 | 0.0% | Pending +SHC_3BB0A8C1_0x0052F730 | 45.4% | branch shape differs SHC_3BB0A8C1_0x0052F7E0 | 0.0% | Pending From 6b2b8813928dd04de3fa9ad202fe9e6638bcb108 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:36 +0200 Subject: [PATCH 108/299] reimplement: SHC_3BB0A8C1_0x00532F80 12.59% orig walks 2 arrays by ptr --- ...istanceToNearestEnemyForLegacyMissions.cpp | 56 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/computeDistanceToNearestEnemyForLegacyMissions.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/computeDistanceToNearestEnemyForLegacyMissions.cpp b/src/OpenSHC/Map/Units/UnitsState/computeDistanceToNearestEnemyForLegacyMissions.cpp new file mode 100644 index 000000000..326fb3e15 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/computeDistanceToNearestEnemyForLegacyMissions.cpp @@ -0,0 +1,56 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Game/GameMode.hpp" + +#include "OpenSHC/Globals/DAT_GameState.hpp" +#include "OpenSHC/Globals/DAT_GameSynchronyState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Game::GameMode; + + // FUNCTION: STRONGHOLDCRUSADER 0x00532F80 + int UnitsState::computeDistanceToNearestEnemyForLegacyMissions(int unitID) + { + if (DAT_GameSynchronyState::instance.currentGameMode != OpenSHC::Game::GM_SOLITARY) { + return 10000; + } + if ((int)this->unitCount >= 100) { + return 10000; + } + short _owner = this->units[unitID].owner; + int _unitMicroX = this->units[unitID].microXPosition; + int _unitMicroY = this->units[unitID].microYPosition; + int _closestDistance = 10000; + for (int i = 0; i < DAT_GameState::instance.playerDataArray[_owner].enemies; ++i) { + short _enemyUnitID = DAT_GameState::instance.playerDataArray[_owner].enemyIDArray[i]; + if (this->units[_enemyUnitID].uid + != DAT_GameState::instance.mapAndTime.playerEnemenyUnitUIDShortList[_owner][i]) { + continue; + } + int _distanceX = this->units[_enemyUnitID].microXPosition; + if (_distanceX < _unitMicroX) { + _distanceX = _unitMicroX - _distanceX; + } else { + _distanceX = _distanceX - _unitMicroX; + } + int _distanceY = this->units[_enemyUnitID].microYPosition; + if (_distanceY < _unitMicroY) { + _distanceY = _unitMicroY - _distanceY; + } else { + _distanceY = _distanceY - _unitMicroY; + } + if (_distanceY <= _distanceX) { + _distanceY = _distanceX; + } + if (_distanceY < _closestDistance) { + _closestDistance = _distanceY; + } + } + return _closestDistance; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 6ebfd04ae..1ddff182d 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -50645,7 +50645,7 @@ SHC_3BB0A8C1_0x00532F5E | 0.0% | Pending SHC_3BB0A8C1_0x00532F60 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x00532F80 | 0.0% | Pending +SHC_3BB0A8C1_0x00532F80 | 12.6% | orig walks 2 arrays by ptr SHC_3BB0A8C1_0x00533010 | 0.0% | Pending From b450b679684cf1e33ed7ae8f99c931a4b0dbaab1 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:36 +0200 Subject: [PATCH 109/299] reimplement: SHC_3BB0A8C1_0x00533CA0 90.91% loop exit shape differs --- .../tracePathFromLadderExitSetDestination.cpp | 43 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/tracePathFromLadderExitSetDestination.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/tracePathFromLadderExitSetDestination.cpp b/src/OpenSHC/Map/Units/UnitsState/tracePathFromLadderExitSetDestination.cpp new file mode 100644 index 000000000..567fbd6bc --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/tracePathFromLadderExitSetDestination.cpp @@ -0,0 +1,43 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" + +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + // FUNCTION: STRONGHOLDCRUSADER 0x00533CA0 + void UnitsState::tracePathFromLadderExitSetDestination(int unitID) + { + int _exitX = this->units[unitID].ladderExitXPosition; + int _exitY = this->units[unitID].ladderExitYPosition; + int _tile = this->units[unitID].previousTilePosition; + int _stepIndex = 0; + for (; _stepIndex < this->units[unitID].totalSizeOfPathPlan; ++_stepIndex) { + uint _packedDirections = (char)this->units[unitID].pathPlanStart[_stepIndex / 2]; + uint _direction; + if ((_stepIndex & 1) == 0) { + _direction = _packedDirections & 0xf; + } else { + _direction = (int)_packedDirections >> 4; + } + _exitY = _exitY + + DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction].int_.yOffset; + _exitX = _exitX + + DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction].int_.xOffset; + _tile = DAT_ViewportRenderState::instance.translationMatrix[_exitY].addXgetTile + _exitX; + if ((DAT_TileMapState::instance.LogicLayer[_tile] & 0x800U) != 0) { + break; + } + } + this->units[unitID].destinationYPosition = (short)_exitY; + this->units[unitID].totalSizeOfPathPlan = (short)_stepIndex + 1; + this->units[unitID].destinationXPosition = (short)_exitX; + this->units[unitID].destinationTilePosition = _tile; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 1ddff182d..5295ba854 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -50691,7 +50691,7 @@ SHC_3BB0A8C1_0x00533B30 | 0.0% | Pending SHC_3BB0A8C1_0x00533C70 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x00533CA0 | 0.0% | Pending +SHC_3BB0A8C1_0x00533CA0 | 90.9% | loop exit shape differs SHC_3BB0A8C1_0x00533D50 | 0.0% | Pending From e559048f7c1bf97dca66f9c0a6a645a1ec55e756 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:37 +0200 Subject: [PATCH 110/299] reimplement: SHC_3BB0A8C1_0x0053A070 64.00% orig caches state local --- .../isWorkerAtProductionIdleState.cpp | 69 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/isWorkerAtProductionIdleState.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/isWorkerAtProductionIdleState.cpp b/src/OpenSHC/Map/Units/UnitsState/isWorkerAtProductionIdleState.cpp new file mode 100644 index 000000000..a97a0823c --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/isWorkerAtProductionIdleState.cpp @@ -0,0 +1,69 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Map/Units/States/UnitState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Map::Units::States::UnitState; + + // FUNCTION: STRONGHOLDCRUSADER 0x0053A070 + undefined4 UnitsState::isWorkerAtProductionIdleState(int unitID) + { + switch (this->units[unitID].unitType) { + case OpenSHC::Map::Units::UT_WOODCUTTER: + case OpenSHC::Map::Units::UT_HOPSFARMER: + case OpenSHC::Map::Units::UT_MILLER: + case OpenSHC::Map::Units::UT_BREWER: + case OpenSHC::Map::Units::UT_POLETURNER: + case OpenSHC::Map::Units::UT_SMITH: + case OpenSHC::Map::Units::UT_ARMORER: + case OpenSHC::Map::Units::UT_TANNER: + if (this->units[unitID].state.generic == OpenSHC::Map::Units::States::US_STAND_UPUnk) { + return 1; + } + break; + case OpenSHC::Map::Units::UT_FLETCHER: + case OpenSHC::Map::Units::UT_APPLEFARMER: + if (this->units[unitID].state.generic == OpenSHC::Map::Units::States::US_LOOK_AROUNDUnk) { + return 1; + } + break; + case OpenSHC::Map::Units::UT_HUNTER: + case OpenSHC::Map::Units::UT_DAIRYFARMER: + if (this->units[unitID].state.generic == OpenSHC::Map::Units::States::US_AIM_WEAPONUnk) { + return 1; + } + break; + case OpenSHC::Map::Units::UT_QUARRYWORKER: + case OpenSHC::Map::Units::UT_PITCHMAN: + if (this->units[unitID].state.generic == (UnitState)3) { + return 1; + } + break; + case OpenSHC::Map::Units::UT_QUARRYOX: + if (this->units[unitID].state.generic == OpenSHC::Map::Units::States::US_IDLEUnk) { + return 1; + } + break; + case OpenSHC::Map::Units::UT_WHEATFARMER: + if (this->units[unitID].state.generic == (UnitState)10) { + return 1; + } + break; + case OpenSHC::Map::Units::UT_BAKER: + if (this->units[unitID].state.generic == OpenSHC::Map::Units::States::US_FIRE_WEAPONUnk) { + return 1; + } + break; + case OpenSHC::Map::Units::UT_TRANSPORTMINER: + if (this->units[unitID].state.generic == OpenSHC::Map::Units::States::US_RELOAD_WEAPONUnk) { + return 1; + } + } + return 0; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 5295ba854..af24a037d 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -59427,7 +59427,7 @@ SHC_3BB0A8C1_0x0053A018 | 0.0% | Pending SHC_3BB0A8C1_0x0053A020 | 0.0% | Pending -SHC_3BB0A8C1_0x0053A070 | 0.0% | Pending +SHC_3BB0A8C1_0x0053A070 | 64.0% | orig caches state local SHC_3BB0A8C1_0x0053A108 | 0.0% | Pending From 1f8ce2a2d8858e0ec757056a676a4b1cb1774218 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:37 +0200 Subject: [PATCH 111/299] reimplement: SHC_3BB0A8C1_0x00536400 38.89% branch shape differs --- .../countSelectedCatapultsAndTrebuchets.cpp | 57 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/countSelectedCatapultsAndTrebuchets.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/countSelectedCatapultsAndTrebuchets.cpp b/src/OpenSHC/Map/Units/UnitsState/countSelectedCatapultsAndTrebuchets.cpp new file mode 100644 index 000000000..632775141 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/countSelectedCatapultsAndTrebuchets.cpp @@ -0,0 +1,57 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Map/Units/UnitLogicState.hpp" +#include "OpenSHC/Map/Units/UnitType.hpp" + +#include "OpenSHC/Globals/DAT_CurrentUnitSlotID.hpp" +#include "OpenSHC/Globals/DAT_GameState.hpp" +#include "OpenSHC/Globals/DAT_GameSynchronyState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Map::Units::UnitLogicState; + using OpenSHC::Map::Units::UnitType; + + // FUNCTION: STRONGHOLDCRUSADER 0x00536400 + undefined4 UnitsState::countSelectedCatapultsAndTrebuchets() + { + this->field15_0x560 = 0; + if (DAT_GameState::instance.playerDataArray[DAT_GameSynchronyState::instance.currentPlayerSlotID].keep.id + < 1) { + return 0; + } + int _count = 0; + for (DAT_CurrentUnitSlotID::instance = 1; (int)DAT_CurrentUnitSlotID::instance < (int)this->maxUnitCount; + DAT_CurrentUnitSlotID::instance = DAT_CurrentUnitSlotID::instance + 1) { + if (this->units[DAT_CurrentUnitSlotID::instance].logicalState != OpenSHC::Map::Units::ULS_NORMAL) { + continue; + } + if (this->units[DAT_CurrentUnitSlotID::instance].dying != 0) { + continue; + } + if (this->units[DAT_CurrentUnitSlotID::instance].isSelected == 0) { + continue; + } + if (this->units[DAT_CurrentUnitSlotID::instance].owner + != DAT_GameSynchronyState::instance.currentPlayerSlotID) { + return 0; + } + if (this->units[DAT_CurrentUnitSlotID::instance].unitType == OpenSHC::Map::Units::UT_S_CATAPULT + || this->units[DAT_CurrentUnitSlotID::instance].unitType == OpenSHC::Map::Units::UT_S_TREBUCHET) { + _count = _count + 1; + this->field15_0x560 = DAT_CurrentUnitSlotID::instance; + } + } + if (_count == 1) { + return 1; + } + if (_count > 1) { + return 2; + } + return 0; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index af24a037d..56359eb5d 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -51125,7 +51125,7 @@ SHC_3BB0A8C1_0x00536310 | 0.0% | Pending SHC_3BB0A8C1_0x00536370 | 77.3% | cond order differs -SHC_3BB0A8C1_0x00536400 | 0.0% | Pending +SHC_3BB0A8C1_0x00536400 | 38.9% | branch shape differs SHC_3BB0A8C1_0x00536440 | 0.0% | Pending From 3b0ab39c70914c2e27cdec39b472c28d6383c8ca Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:38 +0200 Subject: [PATCH 112/299] reimplement: SHC_3BB0A8C1_0x0052F680 58.33% branch shape differs --- .../triggerDesyncIfTileUnitLinkageInvalid.cpp | 48 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/triggerDesyncIfTileUnitLinkageInvalid.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/triggerDesyncIfTileUnitLinkageInvalid.cpp b/src/OpenSHC/Map/Units/UnitsState/triggerDesyncIfTileUnitLinkageInvalid.cpp new file mode 100644 index 000000000..15bd76dbd --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/triggerDesyncIfTileUnitLinkageInvalid.cpp @@ -0,0 +1,48 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Synchrony/GameSynchronyState.func.hpp" +#include "OpenSHC/Commands/GameCommandType.hpp" +#include "OpenSHC/Game/GameMode.hpp" + +#include "OpenSHC/Globals/DAT_GameState.hpp" +#include "OpenSHC/Globals/DAT_GameSynchronyState.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Commands::GameCommandType; + using OpenSHC::Game::GameMode; + + // FUNCTION: STRONGHOLDCRUSADER 0x0052F680 + void UnitsState::triggerDesyncIfTileUnitLinkageInvalid(int tile) + { + if (DAT_GameSynchronyState::instance.currentGameMode != OpenSHC::Game::GM_SOLITARY + && (DAT_GameSynchronyState::instance.syncStatus != 0 + || DAT_GameSynchronyState::instance.saveRelated != 0)) { + return; + } + if (DAT_GameState::instance.mapAndTime.multiplayerUnitSameTileLinkageTimeWindow != 0) { + return; + } + if ((uint)(short)DAT_TileMapState::instance.UnitLayer[tile] > 2499) { + DAT_GameState::instance.mapAndTime.multiplayerUnitSameTileLinkageTimeWindow = 1; + MACRO_CALL_MEMBER(OpenSHC::Synchrony::GameSynchronyState_Func::queueCommand, + DAT_GameSynchronyState::ptr)((GameCommandType)0x4f); + return; + } + for (uint unitID = (short)DAT_TileMapState::instance.UnitLayer[tile]; unitID != 0; + unitID = (short)this->units[unitID].nextUnitOnTheSameTile) { + if (this->units[unitID].tile != tile && this->units[unitID].usingTeleport == 0 + && this->units[unitID].field303_0x413 == 0) { + DAT_GameState::instance.mapAndTime.multiplayerUnitSameTileLinkageTimeWindow = 1; + MACRO_CALL_MEMBER(OpenSHC::Synchrony::GameSynchronyState_Func::queueCommand, + DAT_GameSynchronyState::ptr)((GameCommandType)0x4f); + return; + } + } + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 56359eb5d..6bffba628 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -49337,7 +49337,7 @@ SHC_3BB0A8C1_0x0052F570 | 0.0% | Pending SHC_3BB0A8C1_0x0052F5B0 | 0.0% | Pending -SHC_3BB0A8C1_0x0052F680 | 0.0% | Pending +SHC_3BB0A8C1_0x0052F680 | 58.3% | branch shape differs SHC_3BB0A8C1_0x0052F6C0 | 0.0% | Pending From 556244bc5ef9215d9a43c88c1432db444f376ab4 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:38 +0200 Subject: [PATCH 113/299] reimplement: SHC_3BB0A8C1_0x00537E00 35.16% orig has 2 separate loops --- .../UnitsState/setTowerSiegeEngineToIdle.cpp | 41 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/setTowerSiegeEngineToIdle.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/setTowerSiegeEngineToIdle.cpp b/src/OpenSHC/Map/Units/UnitsState/setTowerSiegeEngineToIdle.cpp new file mode 100644 index 000000000..98cb64a8d --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/setTowerSiegeEngineToIdle.cpp @@ -0,0 +1,41 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Map/Units/States/UnitState.hpp" +#include "OpenSHC/Map/Units/UnitLogicState.hpp" +#include "OpenSHC/Map/Units/UnitType.hpp" + +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Map::Units::UnitLogicState; + using OpenSHC::Map::Units::UnitType; + using OpenSHC::Map::Units::States::UnitState; + + // FUNCTION: STRONGHOLDCRUSADER 0x00537E00 + void UnitsState::setTowerSiegeEngineToIdle(int buildingID) + { + UnitTypeShort _siegeEngineType; + if (DAT_BuildingsState::instance.buildings[buildingID].containsSiegeMangonel1OrBallista2 == 1) { + _siegeEngineType = OpenSHC::Map::Units::UT_S_MANGONEL; + } else if (DAT_BuildingsState::instance.buildings[buildingID].containsSiegeMangonel1OrBallista2 == 2) { + _siegeEngineType = OpenSHC::Map::Units::UT_S_BALLISTA; + } else { + return; + } + for (int unitID = 0; unitID < (int)this->maxUnitCount; ++unitID) { + if (this->units[unitID].logicalState == OpenSHC::Map::Units::ULS_NORMAL + && this->units[unitID].dying == 0 && this->units[unitID].unitType == _siegeEngineType + && DAT_TileMapState::instance.BuildingLayer[this->units[unitID].tile] == buildingID) { + this->units[unitID].state.generic + = (OpenSHC::Map::Units::States::US_STAND_UPUnk | OpenSHC::Map::Units::States::US_IDLEUnk); + return; + } + } + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 6bffba628..f2432f0df 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -51259,7 +51259,7 @@ SHC_3BB0A8C1_0x00537C90 | 0.0% | Pending SHC_3BB0A8C1_0x00537D60 | 14.6% | orig uses global instance -SHC_3BB0A8C1_0x00537E00 | 0.0% | Pending +SHC_3BB0A8C1_0x00537E00 | 35.2% | orig has 2 separate loops SHC_3BB0A8C1_0x00537EE0 | 100.0% | Reimplemented From ef7f20308bb3e60be69ee2e5e53b19f12c83d56a Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:38 +0200 Subject: [PATCH 114/299] reimplement: SHC_3BB0A8C1_0x00530400 100.00% Reimplemented --- .../transferNonCourtUnitsToPlayer.cpp | 59 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/transferNonCourtUnitsToPlayer.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/transferNonCourtUnitsToPlayer.cpp b/src/OpenSHC/Map/Units/UnitsState/transferNonCourtUnitsToPlayer.cpp new file mode 100644 index 000000000..10aa2cb89 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/transferNonCourtUnitsToPlayer.cpp @@ -0,0 +1,59 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Map/Units/States/UnitState.hpp" +#include "OpenSHC/Map/Units/UnitLogicState.hpp" +#include "OpenSHC/Map/Units/UnitType.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Map::Units::UnitLogicState; + using OpenSHC::Map::Units::UnitType; + using OpenSHC::Map::Units::States::UnitState; + + // FUNCTION: STRONGHOLDCRUSADER 0x00530400 + void UnitsState::transferNonCourtUnitsToPlayer(int fromPlayer, int toPlayer) + { + for (int unitID = 1; unitID < 2500; ++unitID) { + if (this->units[unitID].logicalState != OpenSHC::Map::Units::ULS_NORMAL) { + continue; + } + if (this->units[unitID].dying != 0) { + continue; + } + if (this->units[unitID].isStalked != 0) { + switch (this->units[unitID].unitType) { + case OpenSHC::Map::Units::UT_QUARRYOX: + case OpenSHC::Map::Units::UT_COW: + case OpenSHC::Map::Units::UT_HUNTERDOG: + case OpenSHC::Map::Units::UT_CHICKEN: + case OpenSHC::Map::Units::UT_MOTHER: + case OpenSHC::Map::Units::UT_CHILD: + case OpenSHC::Map::Units::UT_JUGGLER: + case OpenSHC::Map::Units::UT_FIREEATER: + break; + default: + continue; + } + } + if (this->units[unitID].owner != fromPlayer) { + continue; + } + if (this->units[unitID].unitType == OpenSHC::Map::Units::UT_LORD) { + this->units[unitID].state.generic = OpenSHC::Map::Units::States::US_DISAPPEAR; + } else if (this->units[unitID].unitType == OpenSHC::Map::Units::UT_LADY) { + this->units[unitID].state.generic = OpenSHC::Map::Units::States::US_DISAPPEAR; + } else if (this->units[unitID].unitType == OpenSHC::Map::Units::UT_JESTER) { + this->units[unitID].state.generic = OpenSHC::Map::Units::States::US_DISAPPEAR; + } else { + this->units[unitID].owner = (short)toPlayer; + if (this->units[unitID].isStalked == 0 || this->units[unitID].calculatedOwnerPlayerIndex != 0) { + this->units[unitID].calculatedOwnerPlayerIndex = toPlayer; + } + } + } + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index f2432f0df..39929972d 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -49379,7 +49379,7 @@ SHC_3BB0A8C1_0x00530390 | 100.0% | Reimplemented SHC_3BB0A8C1_0x005303B0 | 0.0% | Pending -SHC_3BB0A8C1_0x00530400 | 0.0% | Pending +SHC_3BB0A8C1_0x00530400 | 100.0% | Reimplemented SHC_3BB0A8C1_0x005304B4 | 0.0% | Pending From 6b2f342960d631fcc83c1eda65905496d58816bb Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:39 +0200 Subject: [PATCH 115/299] reimplement: SHC_3BB0A8C1_0x005346D0 32.12% orig walks unit ptr --- .../UnitsState/selectNewBlessingTarget.cpp | 57 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/selectNewBlessingTarget.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/selectNewBlessingTarget.cpp b/src/OpenSHC/Map/Units/UnitsState/selectNewBlessingTarget.cpp new file mode 100644 index 000000000..6c99f1b0d --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/selectNewBlessingTarget.cpp @@ -0,0 +1,57 @@ +#include "OpenSHC/Map/Navigation/DirectionAlgorithmState.func.hpp" +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Map/Units/UnitLogicState.hpp" + +#include "OpenSHC/Globals/DAT_DirectionAlgorithmState.hpp" +#include "OpenSHC/Globals/DAT_UnitPropertiesDefinedData.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Map::Units::UnitLogicState; + + // FUNCTION: STRONGHOLDCRUSADER 0x005346D0 + int UnitsState::selectNewBlessingTarget(int unitID) + { + short _playerID = this->units[unitID].owner; + short _x = this->units[unitID].x; + short _y = this->units[unitID].y; + int _bestUnitID = 0; + int _highestPreference = 0; + for (int _targetUnitID = 1; _targetUnitID < (int)this->maxUnitCount; ++_targetUnitID) { + if (this->units[_targetUnitID].logicalState != OpenSHC::Map::Units::ULS_NORMAL) { + continue; + } + if (this->units[_targetUnitID].dying != 0) { + continue; + } + if (this->units[_targetUnitID].owner != _playerID) { + continue; + } + if (DAT_UnitPropertiesDefinedData::instance.NotBlessableUnits[this->units[_targetUnitID].unitType] + != 0) { + continue; + } + if (this->units[_targetUnitID].blessedAmount >= 4000) { + continue; + } + int _distance = MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::DirectionAlgorithmState_Func::setAxisBasedDistanceResult, + DAT_DirectionAlgorithmState::ptr)( + _x, _y, this->units[_targetUnitID].x, this->units[_targetUnitID].y); + if (_distance >= 40) { + continue; + } + int _preference = ((4000 - this->units[_targetUnitID].blessedAmount) >> 6) - _distance / 2; + if (_highestPreference < _preference) { + _highestPreference = _preference; + _bestUnitID = _targetUnitID; + } + } + return _bestUnitID; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 39929972d..b7eb7cfb2 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -50819,7 +50819,7 @@ SHC_3BB0A8C1_0x005345A0 | 0.0% | Pending SHC_3BB0A8C1_0x005345D0 | 0.0% | Pending -SHC_3BB0A8C1_0x005346D0 | 0.0% | Pending +SHC_3BB0A8C1_0x005346D0 | 32.1% | orig walks unit ptr SHC_3BB0A8C1_0x005347E0 | 0.0% | Pending From 4008a1dbb8108077f5477afb74ddafa654d95617 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:39 +0200 Subject: [PATCH 116/299] reimplement: SHC_3BB0A8C1_0x0053E6C0 83.72% branch shape differs --- .../Map/Units/UnitsState/changeUnitType.cpp | 47 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/changeUnitType.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/changeUnitType.cpp b/src/OpenSHC/Map/Units/UnitsState/changeUnitType.cpp new file mode 100644 index 000000000..ca0faa15c --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/changeUnitType.cpp @@ -0,0 +1,47 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Game/GameMode.hpp" +#include "OpenSHC/Map/Units/UnitLogicState.hpp" + +#include "OpenSHC/Globals/DAT_GameSynchronyState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Game::GameMode; + using OpenSHC::Map::Units::UnitLogicState; + + // FUNCTION: STRONGHOLDCRUSADER 0x0053E6C0 + int UnitsState::changeUnitType(int unitID) + { + this->units[unitID].state.generic = this->units[unitID].state_2; + UnitTypeShort _previousUnitType = this->units[unitID].unitType; + this->units[unitID].logicalState = OpenSHC::Map::Units::ULS_NORMAL; + this->units[unitID].goToRallyPoint = 1; + this->units[unitID].unitType_3 = _previousUnitType; + this->units[unitID].substate = -1; + if (DAT_GameSynchronyState::instance.currentGameMode == OpenSHC::Game::GM_SOLITARY) { + /* < E_ARCHER (basic worker?) */ + if ((short)this->units[unitID].unitTypeToChangeInto < 0x16) { + this->units[unitID].calculatedOwnerPlayerIndex = 0; + } else if ((short)this->units[unitID].unitTypeToChangeInto < 0x1f + || (short)this->units[unitID].unitTypeToChangeInto > 0x45) { + /* is army member */ + this->units[unitID].calculatedOwnerPlayerIndex = this->units[unitID].owner; + } else { + this->units[unitID].calculatedOwnerPlayerIndex = 0; + } + if (this->units[unitID].calculatedOwnerPlayerIndex == 0 && this->units[unitID].owner >= 2) { + this->units[unitID].calculatedOwnerPlayerIndex = this->units[unitID].owner; + } + } else { + this->units[unitID].calculatedOwnerPlayerIndex = this->units[unitID].owner; + } + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::setUnitValues, this)( + unitID, (UnitType)(short)this->units[unitID].unitTypeToChangeInto); + return unitID; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index b7eb7cfb2..ff6d10795 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -60087,7 +60087,7 @@ SHC_3BB0A8C1_0x0053E390 | 0.0% | Pending SHC_3BB0A8C1_0x0053E440 | 0.0% | Pending -SHC_3BB0A8C1_0x0053E6C0 | 0.0% | Pending +SHC_3BB0A8C1_0x0053E6C0 | 83.7% | branch shape differs SHC_3BB0A8C1_0x0053E790 | 36.4% | orig uses global instance From 0d5e80d21105ee0251c5ef547c39286e0a672da4 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:39 +0200 Subject: [PATCH 117/299] reimplement: SHC_3BB0A8C1_0x0053E390 55.17% version ladder shape --- .../UnitsState/upgradeMapFormatForUnits.cpp | 58 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/upgradeMapFormatForUnits.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/upgradeMapFormatForUnits.cpp b/src/OpenSHC/Map/Units/UnitsState/upgradeMapFormatForUnits.cpp new file mode 100644 index 000000000..09366101e --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/upgradeMapFormatForUnits.cpp @@ -0,0 +1,58 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Map/Version.func.hpp" +#include "OpenSHC/IO/PackagedFileMagicNum.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::IO::PackagedFileMagicNum; + + // FUNCTION: STRONGHOLDCRUSADER 0x0053E390 + void UnitsState::upgradeMapFormatForUnits( + PackagedFileMagicNum receivedMapVersion, PackagedFileMagicNum packagerMapVersion) + { + MACRO_CALL(OpenSHC::Map::Version_Func::UpgradeMapUnitsTo_UnknownVersion1)(); + MACRO_CALL(OpenSHC::Map::Version_Func::UpgradeMapUnitsTo_117)(); + MACRO_CALL(OpenSHC::Map::Version_Func::UpgradeMapUnitsTo_UnknownVersion2)(); + if (receivedMapVersion == packagerMapVersion) { + return; + } + if (receivedMapVersion == (PackagedFileMagicNum)100) { + MACRO_CALL(OpenSHC::Map::Version_Func::UpgradeMapUnitsTo_100)(); + MACRO_CALL(OpenSHC::Map::Version_Func::UpgradeMapUnitsTo_112)(); + } else if ((int)receivedMapVersion <= 0x70) { + MACRO_CALL(OpenSHC::Map::Version_Func::UpgradeMapUnitsTo_112)(); + } + if ((int)receivedMapVersion < 0x72) { + MACRO_CALL(OpenSHC::Map::Version_Func::UpgradeMapUnitsTo_114)(); + } + if ((int)receivedMapVersion < 0x75) { + MACRO_CALL(OpenSHC::Map::Version_Func::UpgradeMapUnitsTo_117)(); + } + if ((int)receivedMapVersion < 0x7a) { + MACRO_CALL(OpenSHC::Map::Version_Func::UpgradeMapUnitsAttackTileLogicTo_122)(); + } + if ((int)receivedMapVersion < 0x82) { + MACRO_CALL(OpenSHC::Map::Version_Func::UpgradeMapUnitsTo_130)(); + } + if ((int)receivedMapVersion < 0x95) { + MACRO_CALL(OpenSHC::Map::Version_Func::UpgradeMapUnitsTo_149)(); + } + if ((int)receivedMapVersion < 0x9a) { + MACRO_CALL(OpenSHC::Map::Version_Func::UpgradeMapUnitsTo_154)(); + } + if ((int)receivedMapVersion < 0x9b) { + MACRO_CALL(OpenSHC::Map::Version_Func::UpgradeMapUnitsTo_155)(); + } + if ((int)receivedMapVersion < 0xa9) { + MACRO_CALL(OpenSHC::Map::Version_Func::UpgradeMapUnitsLordHealthTo_169)(); + } + if ((int)receivedMapVersion < 0xaa) { + MACRO_CALL(OpenSHC::Map::Version_Func::UpgradeMapUnitsTo_170)(); + } + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index ff6d10795..73c406235 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -60083,7 +60083,7 @@ SHC_3BB0A8C1_0x0053E380 | 0.0% | Pending SHC_3BB0A8C1_0x0053E384 | 0.0% | Pending -SHC_3BB0A8C1_0x0053E390 | 0.0% | Pending +SHC_3BB0A8C1_0x0053E390 | 55.2% | version ladder shape SHC_3BB0A8C1_0x0053E440 | 0.0% | Pending From f6fc4e1e7851b8f411b1d6b8cf5aa792cb9208ea Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:40 +0200 Subject: [PATCH 118/299] reimplement: SHC_3BB0A8C1_0x005308F0 100.00% Reimplemented --- .../setMissionNumberSpecificLord.cpp | 55 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/setMissionNumberSpecificLord.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/setMissionNumberSpecificLord.cpp b/src/OpenSHC/Map/Units/UnitsState/setMissionNumberSpecificLord.cpp new file mode 100644 index 000000000..ddd6ebcc5 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/setMissionNumberSpecificLord.cpp @@ -0,0 +1,55 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Synchrony/GameSynchronyState.func.hpp" +#include "OpenSHC/Map/Units/UnitLogicState.hpp" +#include "OpenSHC/Map/Units/UnitType.hpp" + +#include "OpenSHC/Globals/DAT_GameSynchronyState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Map::Units::UnitLogicState; + using OpenSHC::Map::Units::UnitType; + + // FUNCTION: STRONGHOLDCRUSADER 0x005308F0 + void UnitsState::setMissionNumberSpecificLord(int missionNumber) + { + if (missionNumber == 5 || missionNumber == 6 || missionNumber == 8 || missionNumber == 15) { + for (int unitID = 1; unitID < (int)this->maxUnitCount; ++unitID) { + if (this->units[unitID].logicalState == OpenSHC::Map::Units::ULS_NORMAL + && this->units[unitID].dying == 0 + && this->units[unitID].owner != DAT_GameSynchronyState::instance.currentPlayerSlotID + && this->units[unitID].unitType == OpenSHC::Map::Units::UT_LORD) { + this->units[unitID].unknownLordTypeBasedMissionSpecificValue_01 = 1; + } + } + return; + } + if (missionNumber <= 15) { + return; + } + for (int unitID = 1; unitID < (int)this->maxUnitCount; ++unitID) { + if (this->units[unitID].logicalState != OpenSHC::Map::Units::ULS_NORMAL) { + continue; + } + if (this->units[unitID].dying != 0) { + continue; + } + if (this->units[unitID].owner == DAT_GameSynchronyState::instance.currentPlayerSlotID) { + continue; + } + if (this->units[unitID].unitType != OpenSHC::Map::Units::UT_LORD) { + continue; + } + if (MACRO_CALL_MEMBER(OpenSHC::Synchrony::GameSynchronyState_Func::getLordTypeForPlayer, + DAT_GameSynchronyState::ptr)(this->units[unitID].owner) + == 1) { + this->units[unitID].unknownLordTypeBasedMissionSpecificValue_01 = 1; + } + } + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 73c406235..5da7c9a3e 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -49635,7 +49635,7 @@ SHC_3BB0A8C1_0x005307B0 | 0.0% | Pending SHC_3BB0A8C1_0x00530880 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x005308F0 | 0.0% | Pending +SHC_3BB0A8C1_0x005308F0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00530990 | 0.0% | Pending From 689eb82a4635e8d2bad00302aaa161670de6c1fe Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:40 +0200 Subject: [PATCH 119/299] reimplement: SHC_3BB0A8C1_0x0052F5B0 24.62% orig fully unrolled x4 --- ...UnitOnSameTileIsLadderInRightDirection.cpp | 30 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/ifAnyUnitOnSameTileIsLadderInRightDirection.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/ifAnyUnitOnSameTileIsLadderInRightDirection.cpp b/src/OpenSHC/Map/Units/UnitsState/ifAnyUnitOnSameTileIsLadderInRightDirection.cpp new file mode 100644 index 000000000..a43f693a3 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/ifAnyUnitOnSameTileIsLadderInRightDirection.cpp @@ -0,0 +1,30 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +#include "OpenSHC/Globals/DAT_TileMapState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x0052F5B0 + undefined4 UnitsState::ifAnyUnitOnSameTileIsLadderInRightDirection(int tile, int y) + { + for (int direction = 0; direction < 8; direction += 2) { + int _neighbourTile = DAT_TileMapState::instance.directionTranslationMatrix[y][direction] + tile; + if ((DAT_TileMapState::instance.LogicLayer[_neighbourTile] & 0x4a5015b1U) == 0 + && DAT_TileMapState::instance.UnitLayer[_neighbourTile] != 0 + && MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::ifAnyUnitOnSameTileIsLadder, this)( + _neighbourTile) + != FALSE) { + return 1; + } + } + return 0; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 5da7c9a3e..c087481d5 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -49335,7 +49335,7 @@ SHC_3BB0A8C1_0x0052F550 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0052F570 | 0.0% | Pending -SHC_3BB0A8C1_0x0052F5B0 | 0.0% | Pending +SHC_3BB0A8C1_0x0052F5B0 | 24.6% | orig fully unrolled x4 SHC_3BB0A8C1_0x0052F680 | 58.3% | branch shape differs From 4c7e83be156c0faed7cde6f7e165b8e4c97bc7f1 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:41 +0200 Subject: [PATCH 120/299] reimplement: SHC_3BB0A8C1_0x0052FD00 83.10% orig caches dir in locals --- .../setUnitFacingDirectionTowardsTarget.cpp | 61 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/setUnitFacingDirectionTowardsTarget.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/setUnitFacingDirectionTowardsTarget.cpp b/src/OpenSHC/Map/Units/UnitsState/setUnitFacingDirectionTowardsTarget.cpp new file mode 100644 index 000000000..451b56c2e --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/setUnitFacingDirectionTowardsTarget.cpp @@ -0,0 +1,61 @@ +#include "OpenSHC/Map/Navigation/DirectionAlgorithmState.func.hpp" +#include "OpenSHC/Map/Units/UnitsState.func.hpp" + +#include "OpenSHC/Globals/DAT_DirectionAlgorithmState.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + // FUNCTION: STRONGHOLDCRUSADER 0x0052FD00 + undefined4 UnitsState::setUnitFacingDirectionTowardsTarget(int unitID, int targetUnitID) + { + if (targetUnitID < 1) { + return 0; + } + MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::DirectionAlgorithmState_Func::calculatePreferredRelativeOrientation, + DAT_DirectionAlgorithmState::ptr)( + this->units[unitID].x, this->units[unitID].y, this->units[targetUnitID].x, this->units[targetUnitID].y); + if (DAT_DirectionAlgorithmState::instance.orientation == 15) { + return 0; + } + if (this->units[unitID].facingDirection == DAT_DirectionAlgorithmState::instance.orientation) { + return 0; + } + int _clockwiseSteps + = DAT_DirectionAlgorithmState::instance.orientation - this->units[unitID].facingDirection; + if (_clockwiseSteps < 0) { + _clockwiseSteps = _clockwiseSteps + 8; + } + int _counterClockwiseSteps + = this->units[unitID].facingDirection - DAT_DirectionAlgorithmState::instance.orientation; + if (_counterClockwiseSteps < 0) { + _counterClockwiseSteps = _counterClockwiseSteps + 8; + } + if (_counterClockwiseSteps < _clockwiseSteps) { + this->units[unitID].facingDirection = this->units[unitID].facingDirection - 1; + } else { + this->units[unitID].facingDirection = this->units[unitID].facingDirection + 1; + } + if (this->units[unitID].facingDirection < 0) { + this->units[unitID].facingDirection = this->units[unitID].facingDirection + 8; + } + if (this->units[unitID].facingDirection > 7) { + this->units[unitID].facingDirection = this->units[unitID].facingDirection - 8; + } + this->units[unitID].facingDirectionMapOrientationCorrected = this->units[unitID].facingDirection; + this->units[unitID].facingDirectionMapOrientationCorrected + = this->units[unitID].facingDirectionMapOrientationCorrected + - (short)DAT_TileMapState::instance.mapOrientation; + if (this->units[unitID].facingDirectionMapOrientationCorrected < 0) { + this->units[unitID].facingDirectionMapOrientationCorrected + = this->units[unitID].facingDirectionMapOrientationCorrected + 8; + } + return 1; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index c087481d5..50d8b4c26 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -49353,7 +49353,7 @@ SHC_3BB0A8C1_0x0052FC30 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0052FCA0 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x0052FD00 | 0.0% | Pending +SHC_3BB0A8C1_0x0052FD00 | 83.1% | orig caches dir in locals SHC_3BB0A8C1_0x0052FE00 | 84.8% | reg alloc differs From 7f14fcb11b58e48fd9ea217d0fd5dd3d5857834c Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:41 +0200 Subject: [PATCH 121/299] reimplement: SHC_3BB0A8C1_0x00537700 16.13% orig caches counter local --- .../Map/Units/UnitsState/findTunnelTarget.cpp | 61 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/findTunnelTarget.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/findTunnelTarget.cpp b/src/OpenSHC/Map/Units/UnitsState/findTunnelTarget.cpp new file mode 100644 index 000000000..901277a63 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/findTunnelTarget.cpp @@ -0,0 +1,61 @@ +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_PathFindingState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x00537700 + BOOLEnum UnitsState::findTunnelTarget(int originBuildingID, int targetPlayer) + { + if ((int)DAT_BuildingsState::instance.buildings[originBuildingID].tunnelerCounter < 0) { + return FALSE; + } + int _distance; + if ((int)DAT_BuildingsState::instance.buildings[originBuildingID].tunnelerCounter < 1) { + _distance = 20; + } else if ((int)DAT_BuildingsState::instance.buildings[originBuildingID].tunnelerCounter < 2) { + _distance = 20; + } else if ((int)DAT_BuildingsState::instance.buildings[originBuildingID].tunnelerCounter < 3) { + _distance = 40; + } else if ((int)DAT_BuildingsState::instance.buildings[originBuildingID].tunnelerCounter < 4) { + _distance = 40; + } else { + if ((int)DAT_BuildingsState::instance.buildings[originBuildingID].tunnelerCounter > 5) { + DAT_BuildingsState::instance.buildings[originBuildingID].tunnelerCounter = -1; + return FALSE; + } + _distance = 80; + } + ushort _tunnelStartY; + if ((DAT_BuildingsState::instance.buildings[originBuildingID].tunnelerCounter & 1) == 0) { + DAT_BuildingsState::instance.buildings[originBuildingID].someX + = DAT_BuildingsState::instance.buildings[originBuildingID].x; + _tunnelStartY = DAT_BuildingsState::instance.buildings[originBuildingID].y - 1; + } else { + DAT_BuildingsState::instance.buildings[originBuildingID].someX + = DAT_BuildingsState::instance.buildings[originBuildingID].x - 1; + _tunnelStartY = DAT_BuildingsState::instance.buildings[originBuildingID].y; + } + DAT_BuildingsState::instance.buildings[originBuildingID].tunnelerCounter + = DAT_BuildingsState::instance.buildings[originBuildingID].tunnelerCounter + 1; + DAT_BuildingsState::instance.buildings[originBuildingID].someY = _tunnelStartY; + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::algTunnelerFindTarget, + DAT_PathFindingState::ptr)(DAT_BuildingsState::instance.buildings[originBuildingID].owner, targetPlayer, + _distance, DAT_BuildingsState::instance.buildings[originBuildingID].someX, (short)_tunnelStartY); + if (DAT_PathFindingState::instance.ALG_TargetTile == 0) { + return FALSE; + } + DAT_BuildingsState::instance.buildings[originBuildingID].tunnelerCounter = -1; + return TRUE; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 50d8b4c26..2366903d7 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -51235,7 +51235,7 @@ SHC_3BB0A8C1_0x005371E0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x005371F0 | 0.0% | Pending -SHC_3BB0A8C1_0x00537700 | 0.0% | Pending +SHC_3BB0A8C1_0x00537700 | 16.1% | orig caches counter local SHC_3BB0A8C1_0x005377F0 | 100.0% | Reimplemented From 1bbf2cf2ec1f1feb498de12dc133dc580daf3b8a Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:41 +0200 Subject: [PATCH 122/299] reimplement: SHC_3BB0A8C1_0x00534240 28.99% orig walks matrix row ptrs --- .../UnitsState/stopUnitIfNextToTarget.cpp | 61 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/stopUnitIfNextToTarget.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/stopUnitIfNextToTarget.cpp b/src/OpenSHC/Map/Units/UnitsState/stopUnitIfNextToTarget.cpp new file mode 100644 index 000000000..c6ba33796 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/stopUnitIfNextToTarget.cpp @@ -0,0 +1,61 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" + +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + // FUNCTION: STRONGHOLDCRUSADER 0x00534240 + int UnitsState::stopUnitIfNextToTarget(int unitID) + { + if (this->units[unitID].targetedBuildingTile == 0) { + return 0; + } + if (this->units[unitID].field64_0x90 == 0) { + return 0; + } + uint _tile = 0; + bool _isNear = false; + for (int direction = 0; direction < 8; ++direction) { + _tile = DAT_TileMapState::instance.directionTranslationMatrix[this->units[unitID].y][direction] + + this->units[unitID].tile; + if (_tile == this->units[unitID].targetedBuildingTile) { + _isNear = true; + break; + } + } + if (!_isNear) { + for (int direction = 0; direction < 8 && !_isNear; ++direction) { + uint _neighbourTile + = DAT_TileMapState::instance.directionTranslationMatrix[this->units[unitID].y][direction] + + this->units[unitID].tile; + for (int secondDirection = 0; secondDirection < 8; ++secondDirection) { + if (DAT_TileMapState::instance.directionTranslationMatrix[this->units[unitID].y + + DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[direction] + .int_.yOffset][secondDirection] + + _neighbourTile + == this->units[unitID].targetedBuildingTile) { + _tile = _neighbourTile; + _isNear = true; + break; + } + } + } + } + if (!_isNear) { + return 0; + } + if ((DAT_TileMapState::instance.LogicLayer[_tile] & 0x100U) == 0 + && DAT_TileMapState::instance.BuildingLayer[_tile] == 0) { + return -1; + } + MACRO_CALL_MEMBER( + OpenSHC::Map::Units::UnitsState_Func::makeUnitStopWalkingByClearingPathProgressState, this)(unitID); + return (uint)(this->units[unitID].movementRelated > 7); + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 2366903d7..e7fafa8d5 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -50801,7 +50801,7 @@ SHC_3BB0A8C1_0x005340F0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00534130 | 0.0% | Pending -SHC_3BB0A8C1_0x00534240 | 0.0% | Pending +SHC_3BB0A8C1_0x00534240 | 29.0% | orig walks matrix row ptrs SHC_3BB0A8C1_0x00534380 | 77.6% | orig walks matrix row ptr From 44bd658e81a59b790693e0e99e7532f140b2837d Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:42 +0200 Subject: [PATCH 123/299] reimplement: SHC_3BB0A8C1_0x0052FE90 81.94% orig caches dir in locals --- .../setUnitFacingDirectionForTargetXandY.cpp | 61 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/setUnitFacingDirectionForTargetXandY.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/setUnitFacingDirectionForTargetXandY.cpp b/src/OpenSHC/Map/Units/UnitsState/setUnitFacingDirectionForTargetXandY.cpp new file mode 100644 index 000000000..0c199f18d --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/setUnitFacingDirectionForTargetXandY.cpp @@ -0,0 +1,61 @@ +#include "OpenSHC/Map/Navigation/DirectionAlgorithmState.func.hpp" +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +#include "OpenSHC/Globals/DAT_DirectionAlgorithmState.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x0052FE90 + BOOLEnum UnitsState::setUnitFacingDirectionForTargetXandY(int unitID, int targetX, int targetY) + { + short _previousFacingDirection = this->units[unitID].facingDirection; + MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::DirectionAlgorithmState_Func::calculatePreferredRelativeOrientation, + DAT_DirectionAlgorithmState::ptr)(this->units[unitID].x, this->units[unitID].y, targetX, targetY); + if (DAT_DirectionAlgorithmState::instance.orientation == 15) { + return FALSE; + } + if (this->units[unitID].facingDirection == DAT_DirectionAlgorithmState::instance.orientation) { + return FALSE; + } + int _clockwiseSteps + = DAT_DirectionAlgorithmState::instance.orientation - this->units[unitID].facingDirection; + if (_clockwiseSteps < 0) { + _clockwiseSteps = _clockwiseSteps + 8; + } + int _counterClockwiseSteps + = this->units[unitID].facingDirection - DAT_DirectionAlgorithmState::instance.orientation; + if (_counterClockwiseSteps < 0) { + _counterClockwiseSteps = _counterClockwiseSteps + 8; + } + if (_counterClockwiseSteps < _clockwiseSteps) { + this->units[unitID].facingDirection = this->units[unitID].facingDirection - 1; + } else { + this->units[unitID].facingDirection = this->units[unitID].facingDirection + 1; + } + if (this->units[unitID].facingDirection < 0) { + this->units[unitID].facingDirection = this->units[unitID].facingDirection + 8; + } + if (this->units[unitID].facingDirection > 7) { + this->units[unitID].facingDirection = this->units[unitID].facingDirection - 8; + } + this->units[unitID].facingDirectionMapOrientationCorrected = this->units[unitID].facingDirection; + this->units[unitID].facingDirectionMapOrientationCorrected + = this->units[unitID].facingDirectionMapOrientationCorrected + - (short)DAT_TileMapState::instance.mapOrientation; + if (this->units[unitID].facingDirectionMapOrientationCorrected < 0) { + this->units[unitID].facingDirectionMapOrientationCorrected + = this->units[unitID].facingDirectionMapOrientationCorrected + 8; + } + return (BOOLEnum)(_previousFacingDirection != this->units[unitID].facingDirection); + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index e7fafa8d5..c73921311 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -49357,7 +49357,7 @@ SHC_3BB0A8C1_0x0052FD00 | 83.1% | orig caches dir in locals SHC_3BB0A8C1_0x0052FE00 | 84.8% | reg alloc differs -SHC_3BB0A8C1_0x0052FE90 | 0.0% | Pending +SHC_3BB0A8C1_0x0052FE90 | 81.9% | orig caches dir in locals SHC_3BB0A8C1_0x0052FF80 | 0.0% | Pending From d4e8313cab6191088ff67136f0921ddf2e46864f Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:42 +0200 Subject: [PATCH 124/299] reimplement: SHC_3BB0A8C1_0x00533A10 19.51% orig caches x/y in locals --- .../UnitsState/computeLadderClimbPath.cpp | 50 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/computeLadderClimbPath.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/computeLadderClimbPath.cpp b/src/OpenSHC/Map/Units/UnitsState/computeLadderClimbPath.cpp new file mode 100644 index 000000000..d42835760 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/computeLadderClimbPath.cpp @@ -0,0 +1,50 @@ +#include "OpenSHC/IO/LowLevelMemory.func.hpp" +#include "OpenSHC/Map/Navigation/PathFindingState.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_PathFindingState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x00533A10 + BOOLEnum UnitsState::computeLadderClimbPath(int unitID, uint param_2, int param_3, int param_4) + { + this->units[unitID].climbDataID = 0; + DAT_PathFindingState::instance.climbIsIllegal = 0; + DAT_PathFindingState::instance.allAssassinsUnk = 0; + this->units[unitID].field280_0x3f4 = 0; + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::copyData, DAT_LowLevelMemory::ptr)( + 0x490, &this->units[unitID], this->units); + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 400, '\0', this->units[unitID].pathPlanStart); + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::bindPathPlanToAlgorithmStateAndReset, + DAT_PathFindingState::ptr)(this->units[unitID].pathPlanStart); + DAT_PathFindingState::instance.unitX = this->units[unitID].x; + DAT_PathFindingState::instance.unitY = this->units[unitID].y; + int _pathPlanSize + = MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::commitUnitPathPlanUsingWalkLayer, + DAT_PathFindingState::ptr)(param_2, param_3, param_4); + if (_pathPlanSize < 1) { + return FALSE; + } + this->units[unitID].totalSizeOfPathPlan = (short)_pathPlanSize; + this->units[unitID].ladderExitYPosition = this->units[unitID].y; + this->units[unitID].currentIndexInPathPlan = 0; + this->units[unitID].ladderExitXPosition = this->units[unitID].x; + this->units[unitID].tunnelerFinishedDigging = 2; + this->units[unitID].cannotClimb = 0; + this->units[unitID].previousTilePosition = this->units[unitID].x + + DAT_ViewportRenderState::instance.translationMatrix[this->units[unitID].y].addXgetTile; + return TRUE; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index c73921311..a82945c9c 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -50685,7 +50685,7 @@ SHC_3BB0A8C1_0x005339A0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x005339F0 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x00533A10 | 0.0% | Pending +SHC_3BB0A8C1_0x00533A10 | 19.5% | orig caches x/y in locals SHC_3BB0A8C1_0x00533B30 | 0.0% | Pending From d1177d8283bb52fb04a69e4b9460018b0800f4d5 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:42 +0200 Subject: [PATCH 125/299] reimplement: SHC_3BB0A8C1_0x0052EED0 80.00% orig caches unitType local --- .../Map/Units/UnitsState/assignNameToUnit.cpp | 52 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/assignNameToUnit.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/assignNameToUnit.cpp b/src/OpenSHC/Map/Units/UnitsState/assignNameToUnit.cpp new file mode 100644 index 000000000..a77f71eeb --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/assignNameToUnit.cpp @@ -0,0 +1,52 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Random/RNG.func.hpp" +#include "OpenSHC/Map/Units/UnitType.hpp" + +#include "OpenSHC/Globals/SEC_RNG.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Map::Units::UnitType; + + // FUNCTION: STRONGHOLDCRUSADER 0x0052EED0 + void UnitsState::assignNameToUnit(int unitID) + { + this->units[unitID].rng1_to_70 = 0; + if (this->units[unitID].unitType == OpenSHC::Map::Units::UT_COW) { + this->units[unitID].firstNameIndex = (char)(SEC_RNG::instance.currentNumber2 % 4) + 0x49; + return; + } + if (this->units[unitID].unitType == OpenSHC::Map::Units::UT_CHICKEN) { + this->units[unitID].firstNameIndex = (char)(SEC_RNG::instance.currentNumber2 % 4) + 0x4d; + return; + } + if (this->units[unitID].unitType == OpenSHC::Map::Units::UT_HUNTERDOG) { + this->units[unitID].firstNameIndex = (char)(SEC_RNG::instance.currentNumber2 % 4) + 0x51; + return; + } + if (this->units[unitID].unitType == OpenSHC::Map::Units::UT_QUARRYOX) { + this->units[unitID].firstNameIndex = (char)(SEC_RNG::instance.currentNumber2 % 4) + 0x55; + return; + } + if (this->units[unitID].unitType == OpenSHC::Map::Units::UT_TANNER + || this->units[unitID].unitType == OpenSHC::Map::Units::UT_LADY + || this->units[unitID].unitType == OpenSHC::Map::Units::UT_MOTHER + || this->units[unitID].unitType == OpenSHC::Map::Units::UT_BREWER + || (this->units[unitID].unitType == OpenSHC::Map::Units::UT_CHILD + && this->units[unitID].spriteID == 0x81)) { + /* women */ + this->units[unitID].firstNameIndex = (char)(SEC_RNG::instance.currentNumber2 % 0x14) + 52; + } else { + /* men */ + this->units[unitID].firstNameIndex = (char)(SEC_RNG::instance.currentNumber2 % 0x32) + 1; + } + MACRO_CALL_MEMBER(OpenSHC::Random::RNG_Func::nextRandomNumber2, SEC_RNG::ptr)(); + this->units[unitID].rng1_to_70 = (char)(SEC_RNG::instance.currentNumber2 % 0x46) + 1; + MACRO_CALL_MEMBER(OpenSHC::Random::RNG_Func::nextRandomNumber2, SEC_RNG::ptr)(); + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index a82945c9c..0a127f8bd 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -49313,7 +49313,7 @@ SHC_3BB0A8C1_0x0052EC10 | 0.0% | Pending SHC_3BB0A8C1_0x0052EDC0 | 0.0% | Pending -SHC_3BB0A8C1_0x0052EED0 | 0.0% | Pending +SHC_3BB0A8C1_0x0052EED0 | 80.0% | orig caches unitType local SHC_3BB0A8C1_0x0052F010 | 69.0% | branch shape differs From 999f5c27cd7c463308cb67f9ea924644be7251df Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:43 +0200 Subject: [PATCH 126/299] reimplement: SHC_3BB0A8C1_0x0054C4F0 13.98% orig walks matrix row ptr --- ...ndleUnitMovementWhenTargetingBuildings.cpp | 59 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/handleUnitMovementWhenTargetingBuildings.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/handleUnitMovementWhenTargetingBuildings.cpp b/src/OpenSHC/Map/Units/UnitsState/handleUnitMovementWhenTargetingBuildings.cpp new file mode 100644 index 000000000..3df46c6c6 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/handleUnitMovementWhenTargetingBuildings.cpp @@ -0,0 +1,59 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +#include "OpenSHC/Globals/DAT_TileMapState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x0054C4F0 + int UnitsState::handleUnitMovementWhenTargetingBuildings(int unitID) + { + if (this->units[unitID].targetedBuildingTile == 0) { + return 0; + } + int _directionStep = 1; + if ((DAT_TileMapState::instance.LogicLayer[this->units[unitID].targetedBuildingTile] & 0x100U) != 0) { + _directionStep = 2; + } + uint _buildingTile = 0; + int _directionOfBuilding = 0; + for (; _directionOfBuilding <= 7; _directionOfBuilding += _directionStep) { + _buildingTile + = DAT_TileMapState::instance.directionTranslationMatrix[this->units[unitID].y][_directionOfBuilding] + + this->units[unitID].tile; + if (_buildingTile == this->units[unitID].targetedBuildingTile) { + break; + } + } + if (_directionOfBuilding > 7) { + return 0; + } + uint _isDefensiveStructure = DAT_TileMapState::instance.LogicLayer[_buildingTile] & 0x100; + if (_isDefensiveStructure == 0 && (DAT_TileMapState::instance.LogicLayer[_buildingTile] & 0x40000000U) == 0 + && DAT_TileMapState::instance.BuildingLayer[_buildingTile] == 0) { + return -1; + } + if (MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::ifAnyUnitOnSameTileIsLadder, this)( + this->units[unitID].tile) + == FALSE) { + MACRO_CALL_MEMBER( + OpenSHC::Map::Units::UnitsState_Func::makeUnitStopWalkingByClearingPathProgressState, this)(unitID); + if (this->units[unitID].movementRelated > 7) { + this->units[unitID].destinationX_2Unk = this->units[unitID].x; + this->units[unitID].destinationY_2Unk = this->units[unitID].y; + return 1; + } + } else if (_isDefensiveStructure != 0) { + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::setDestinationNearTargetedBuilding, this)( + unitID, 0); + } + return 0; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 0a127f8bd..085565c5b 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -62505,7 +62505,7 @@ SHC_3BB0A8C1_0x0054BFC0 | 0.0% | Pending SHC_3BB0A8C1_0x0054C1C0 | 0.0% | Pending -SHC_3BB0A8C1_0x0054C4F0 | 0.0% | Pending +SHC_3BB0A8C1_0x0054C4F0 | 14.0% | orig walks matrix row ptr SHC_3BB0A8C1_0x0054C610 | 0.0% | Pending From c756c39a90d9e536f4cea54eb20e2417544e5535 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:43 +0200 Subject: [PATCH 127/299] reimplement: SHC_3BB0A8C1_0x005345A0 61.73% orig walks unit ptr --- .../findEligibleUnitByTimeAndLocation.cpp | 69 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/findEligibleUnitByTimeAndLocation.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/findEligibleUnitByTimeAndLocation.cpp b/src/OpenSHC/Map/Units/UnitsState/findEligibleUnitByTimeAndLocation.cpp new file mode 100644 index 000000000..2e83a0da5 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/findEligibleUnitByTimeAndLocation.cpp @@ -0,0 +1,69 @@ +#include "OpenSHC/Map/Navigation/DirectionAlgorithmState.func.hpp" +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Map/Units/UnitLogicState.hpp" + +#include "OpenSHC/Globals/DAT_DirectionAlgorithmState.hpp" +#include "OpenSHC/Globals/DAT_GameCore.hpp" +#include "OpenSHC/Globals/DAT_UnitPropertiesDefinedData.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Map::Units::UnitLogicState; + + // FUNCTION: STRONGHOLDCRUSADER 0x005345A0 + int UnitsState::findEligibleUnitByTimeAndLocation( + int unitID, int playerID, int unitXPosition, int unitYPosition, int zero1, int zero2) + { + int _bestUnitID = 0; + int _bestScore = 0; + for (int _candidateUnitID = 1; _candidateUnitID < (int)this->maxUnitCount; ++_candidateUnitID) { + if (this->units[_candidateUnitID].logicalState != OpenSHC::Map::Units::ULS_NORMAL) { + continue; + } + if (this->units[_candidateUnitID].dying != 0) { + continue; + } + if (this->units[_candidateUnitID].owner != playerID) { + continue; + } + if (DAT_UnitPropertiesDefinedData::instance.SomeUnitStatMatrix5[this->units[_candidateUnitID].unitType] + != 0) { + continue; + } + if (_candidateUnitID == unitID) { + continue; + } + if (zero2 == 1 || zero2 == 10) { + if (this->units[_candidateUnitID].field131_0x2ac != (short)zero2) { + continue; + } + } + /* DAT_MatchTime - SEC_Units[_candidateUnitID].someMatchTimeVariable */ + int _score + = (DAT_GameCore::instance.mapTimeInTicks - this->units[_candidateUnitID].someMatchTimeVariable) + >> 5; + if (zero1 != 0) { + int _distance = MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::DirectionAlgorithmState_Func::setAxisBasedDistanceResult, + DAT_DirectionAlgorithmState::ptr)( + unitXPosition, unitYPosition, this->units[_candidateUnitID].x, this->units[_candidateUnitID].y); + /* this formula means divide by 4 and round it up. */ + _score = _score - ((_distance + (_distance >> 0x1f & 3U)) >> 2); + } + if (_bestScore < _score) { + _bestScore = _score; + _bestUnitID = _candidateUnitID; + } + } + if (_bestUnitID == 0) { + return 0; + } + this->units[_bestUnitID].someMatchTimeVariable = DAT_GameCore::instance.mapTimeInTicks; + return _bestUnitID; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 085565c5b..24a5e8925 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -50815,7 +50815,7 @@ SHC_3BB0A8C1_0x00534490 | 15.4% | orig unrolled, 16-bit ORs SHC_3BB0A8C1_0x00534520 | 17.4% | orig unrolled, not a loop -SHC_3BB0A8C1_0x005345A0 | 0.0% | Pending +SHC_3BB0A8C1_0x005345A0 | 61.7% | orig walks unit ptr SHC_3BB0A8C1_0x005345D0 | 0.0% | Pending From b695d1bf856b352644d4b1d2dac2eaedb7d3bb79 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:44 +0200 Subject: [PATCH 128/299] reimplement: SHC_3BB0A8C1_0x00535B00 61.82% call+reg alloc differs --- .../createTribeFromSelectedUnits.cpp | 52 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/createTribeFromSelectedUnits.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/createTribeFromSelectedUnits.cpp b/src/OpenSHC/Map/Units/UnitsState/createTribeFromSelectedUnits.cpp new file mode 100644 index 000000000..99b4ae727 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/createTribeFromSelectedUnits.cpp @@ -0,0 +1,52 @@ +#include "OpenSHC/IO/LowLevelMemory.func.hpp" +#include "OpenSHC/Map/Units/TribesState.func.hpp" +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Synchrony/GameSynchronyState.func.hpp" +#include "OpenSHC/Commands/GameCommandType.hpp" +#include "OpenSHC/Map/Units/UnitLogicState.hpp" + +#include "OpenSHC/Globals/DAT_CurrentUnitSlotID.hpp" +#include "OpenSHC/Globals/DAT_GameSynchronyState.hpp" +#include "OpenSHC/Globals/DAT_LowLevelMemory.hpp" +#include "OpenSHC/Globals/DAT_TribesState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Commands::GameCommandType; + using OpenSHC::Map::Units::UnitLogicState; + + // FUNCTION: STRONGHOLDCRUSADER 0x00535B00 + int UnitsState::createTribeFromSelectedUnits() + { + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 400, '\0', this->selectedUnitsBitFlags); + int _selectedCount = 0; + for (DAT_CurrentUnitSlotID::instance = 1; (int)DAT_CurrentUnitSlotID::instance < (int)this->maxUnitCount; + DAT_CurrentUnitSlotID::instance = DAT_CurrentUnitSlotID::instance + 1) { + if (this->units[DAT_CurrentUnitSlotID::instance].logicalState == OpenSHC::Map::Units::ULS_NORMAL + && this->units[DAT_CurrentUnitSlotID::instance].dying == 0 + && this->units[DAT_CurrentUnitSlotID::instance].owner + == DAT_GameSynchronyState::instance.currentPlayerSlotID + && this->units[DAT_CurrentUnitSlotID::instance].isSelected != 0) { + MACRO_CALL_MEMBER(OpenSHC::Map::Units::TribesState_Func::addUnitToSelected, DAT_TribesState::ptr)( + DAT_CurrentUnitSlotID::instance); + _selectedCount = _selectedCount + 1; + } + } + if (_selectedCount == 0) { + return 0; + } + DAT_TribesState::instance.DAT_CurrentTribeID + = MACRO_CALL_MEMBER(OpenSHC::Map::Units::TribesState_Func::getAvailableTribeID, DAT_TribesState::ptr)( + DAT_GameSynchronyState::instance.currentPlayerSlotID); + DAT_GameSynchronyState::instance.DAT_GameCommandParam0 = DAT_TribesState::instance.DAT_CurrentTribeID; + MACRO_CALL_MEMBER(OpenSHC::Synchrony::GameSynchronyState_Func::queueCommand, DAT_GameSynchronyState::ptr)( + OpenSHC::Commands::GCT_UNITS_SELECT); + return _selectedCount; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 24a5e8925..6c6d141d9 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -51099,7 +51099,7 @@ SHC_3BB0A8C1_0x005359C0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00535A30 | 0.0% | Pending -SHC_3BB0A8C1_0x00535B00 | 0.0% | Pending +SHC_3BB0A8C1_0x00535B00 | 61.8% | call+reg alloc differs SHC_3BB0A8C1_0x00535BC0 | 0.0% | Pending From 4ce90ee945dc93975b667c8c559c2aa58e7b7b76 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:44 +0200 Subject: [PATCH 129/299] reimplement: SHC_3BB0A8C1_0x00537C10 48.52% orig walks unit ptr --- .../findClosestEnemyByAreaAndRange.cpp | 72 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/findClosestEnemyByAreaAndRange.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/findClosestEnemyByAreaAndRange.cpp b/src/OpenSHC/Map/Units/UnitsState/findClosestEnemyByAreaAndRange.cpp new file mode 100644 index 000000000..4fa119665 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/findClosestEnemyByAreaAndRange.cpp @@ -0,0 +1,72 @@ +#include "OpenSHC/Map/Navigation/DirectionAlgorithmState.func.hpp" +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Map/Units/States/UnitState.hpp" +#include "OpenSHC/Map/Units/UnitLogicState.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 Units { + + using OpenSHC::Map::Units::UnitLogicState; + using OpenSHC::Map::Units::States::UnitState; + + // FUNCTION: STRONGHOLDCRUSADER 0x00537C10 + int UnitsState::findClosestEnemyByAreaAndRange(int range, uint x, uint y, int playerID) + { + if (x >= 400 || y >= 400) { + return 0; + } + if (*(char*)(y * 400 + 0x21aec98 + x) == '\0') { + return 0; + } + ushort _areaOfOrigin + = DAT_TileMapState::instance + .PathConnectionLayer[DAT_ViewportRenderState::instance.translationMatrix[y].addXgetTile + x]; + this->unusedUnitIDArrayIndex = 0; + int _bestScore = 10000; + int _bestUnitID = 0; + for (int unitID = 1; unitID < (int)this->maxUnitCount; ++unitID) { + if (this->units[unitID].logicalState != OpenSHC::Map::Units::ULS_NORMAL) { + continue; + } + if (this->units[unitID].dying != 0) { + continue; + } + if (this->units[unitID].unknownTestAgainst0_2 != 0) { + continue; + } + if (this->units[unitID].state.generic == OpenSHC::Map::Units::States::US_MELEE_ATTACK) { + continue; + } + if (this->units[unitID].isStalked != 0) { + continue; + } + if (DAT_GameState::instance.mapAndTime.playerTeams[playerID] + == DAT_GameState::instance.mapAndTime.playerTeams[this->units[unitID].owner]) { + continue; + } + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::DirectionAlgorithmState_Func::setAxisBasedDistanceResult, + DAT_DirectionAlgorithmState::ptr)(x, y, this->units[unitID].x, this->units[unitID].y); + if (DAT_DirectionAlgorithmState::instance.distanceHigh > range) { + continue; + } + if (DAT_TileMapState::instance.PathConnectionLayer[this->units[unitID].tile] != _areaOfOrigin) { + continue; + } + int _score = DAT_DirectionAlgorithmState::instance.distanceHigh + this->units[unitID].huntedBy * 3; + if (_score < _bestScore) { + _bestScore = _score; + _bestUnitID = unitID; + } + } + return _bestUnitID; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 6c6d141d9..af84d683e 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -51253,7 +51253,7 @@ SHC_3BB0A8C1_0x00537AA0 | 0.0% | Pending SHC_3BB0A8C1_0x00537B20 | 0.0% | Pending -SHC_3BB0A8C1_0x00537C10 | 0.0% | Pending +SHC_3BB0A8C1_0x00537C10 | 48.5% | orig walks unit ptr SHC_3BB0A8C1_0x00537C90 | 0.0% | Pending From 3ed1d33211d892ad5201131cb41bed9589f0eeeb Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:44 +0200 Subject: [PATCH 130/299] reimplement: SHC_3BB0A8C1_0x00533B30 70.07% orig caches x/y in locals --- .../UnitsState/changeDestinationByAmount.cpp | 53 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/changeDestinationByAmount.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/changeDestinationByAmount.cpp b/src/OpenSHC/Map/Units/UnitsState/changeDestinationByAmount.cpp new file mode 100644 index 000000000..3e24d086a --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/changeDestinationByAmount.cpp @@ -0,0 +1,53 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" + +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + // FUNCTION: STRONGHOLDCRUSADER 0x00533B30 + void UnitsState::changeDestinationByAmount(int unitID, int leftover) + { + if (this->units[unitID].climbDataID != 0) { + this->units[unitID].leftover = (short)leftover; + return; + } + this->units[unitID].leftover = 0; + if (leftover >= this->units[unitID].totalSizeOfPathPlan) { + this->units[unitID].destinationTilePosition = this->units[unitID].previousTilePosition; + this->units[unitID].totalSizeOfPathPlan = 0; + this->units[unitID].destinationXPosition = this->units[unitID].ladderExitXPosition; + this->units[unitID].destinationYPosition = this->units[unitID].ladderExitYPosition; + this->units[unitID].destinationX_2Unk = this->units[unitID].ladderExitXPosition; + this->units[unitID].destinationY_2Unk = this->units[unitID].ladderExitYPosition; + return; + } + int _destinationX = this->units[unitID].ladderExitXPosition; + int _destinationY = this->units[unitID].ladderExitYPosition; + this->units[unitID].totalSizeOfPathPlan = this->units[unitID].totalSizeOfPathPlan - (short)leftover; + for (int _stepIndex = 0; _stepIndex < this->units[unitID].totalSizeOfPathPlan; ++_stepIndex) { + uint _packedDirections = (char)this->units[unitID].pathPlanStart[_stepIndex / 2]; + uint _direction; + if ((_stepIndex & 1) == 0) { + _direction = _packedDirections & 0xf; + } else { + _direction = (int)_packedDirections >> 4; + } + _destinationX = _destinationX + + DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction].int_.xOffset; + _destinationY = _destinationY + + DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction].int_.yOffset; + } + this->units[unitID].destinationXPosition = (short)_destinationX; + this->units[unitID].destinationYPosition = (short)_destinationY; + this->units[unitID].destinationX_2Unk = (short)_destinationX; + this->units[unitID].destinationY_2Unk = (short)_destinationY; + this->units[unitID].destinationTilePosition = (short)_destinationX + + DAT_ViewportRenderState::instance.translationMatrix[(short)_destinationY].addXgetTile; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index af84d683e..adc3665dd 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -50687,7 +50687,7 @@ SHC_3BB0A8C1_0x005339F0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00533A10 | 19.5% | orig caches x/y in locals -SHC_3BB0A8C1_0x00533B30 | 0.0% | Pending +SHC_3BB0A8C1_0x00533B30 | 70.1% | orig caches x/y in locals SHC_3BB0A8C1_0x00533C70 | 100.0% | Reimplemented From c34b16b28de9776fa4ccda2021e1fb68583954b9 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:45 +0200 Subject: [PATCH 131/299] reimplement: SHC_3BB0A8C1_0x00534130 79.73% reg alloc differs --- .../applyTunnelDamageAlongPathPlan.cpp | 55 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/applyTunnelDamageAlongPathPlan.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/applyTunnelDamageAlongPathPlan.cpp b/src/OpenSHC/Map/Units/UnitsState/applyTunnelDamageAlongPathPlan.cpp new file mode 100644 index 000000000..845e4b335 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/applyTunnelDamageAlongPathPlan.cpp @@ -0,0 +1,55 @@ +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" +#include "OpenSHC/Map/TileMapState.func.hpp" +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +#include "OpenSHC/Globals/DAT_PathFindingState.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x00534130 + void UnitsState::applyTunnelDamageAlongPathPlan(uint unitID) + { + uint _xPosition = this->units[unitID].ladderExitXPosition; + uint _yPosition = this->units[unitID].ladderExitYPosition; + int _tile = this->units[unitID].previousTilePosition; + for (int _stepIndex = 0; _stepIndex < this->units[unitID].totalSizeOfPathPlan; ++_stepIndex) { + if ((DAT_TileMapState::instance.LogicLayer[_tile] & 0x20000081U) == 0) { + if (DAT_TileMapState::instance.BuildingLayer[_tile] == 0 + && (DAT_TileMapState::instance.HeightLayer[_tile] < 0x10 + || DAT_TileMapState::instance.DefaultHeightLayer[_tile] < 0x10)) { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::increaseHeightForTunnelWithBrush, + DAT_TileMapState::ptr)(_tile, _xPosition, _yPosition, -2); + DAT_TileMapState::instance.HeightLayer[_tile] = 0; + } else { + MACRO_CALL_MEMBER( + OpenSHC::Map::TileMapState_Func::processDamageToBuilding, DAT_TileMapState::ptr)( + _tile, _xPosition, _yPosition, 5, 0, this->units[unitID].owner, FALSE, 0); + } + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::updateWalkAndPathLayer, + DAT_PathFindingState::ptr)(1, _xPosition, _yPosition); + } + uint _packedDirections = (char)this->units[unitID].pathPlanStart[_stepIndex / 2]; + uint _direction; + if ((_stepIndex & 1) == 0) { + _direction = _packedDirections & 0xf; + } else { + _direction = (int)_packedDirections >> 4; + } + _xPosition = _xPosition + + DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction].int_.xOffset; + _tile = _tile + DAT_TileMapState::instance.directionTranslationMatrix[_yPosition][_direction]; + _yPosition = _yPosition + + DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction].int_.yOffset; + } + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index adc3665dd..1609c819a 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -50799,7 +50799,7 @@ SHC_3BB0A8C1_0x005340E4 | 0.0% | Pending SHC_3BB0A8C1_0x005340F0 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x00534130 | 0.0% | Pending +SHC_3BB0A8C1_0x00534130 | 79.7% | reg alloc differs SHC_3BB0A8C1_0x00534240 | 29.0% | orig walks matrix row ptrs From 1ff12411a8d6debde0f41ba03bf1b6949942b848 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:45 +0200 Subject: [PATCH 132/299] reimplement: SHC_3BB0A8C1_0x00537880 28.57% retry loop shape differs --- .../UnitsState/findNearestShootableDeer.cpp | 71 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/findNearestShootableDeer.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/findNearestShootableDeer.cpp b/src/OpenSHC/Map/Units/UnitsState/findNearestShootableDeer.cpp new file mode 100644 index 000000000..24f1d90d8 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/findNearestShootableDeer.cpp @@ -0,0 +1,71 @@ +#include "OpenSHC/Map/Entities/EntityState.func.hpp" +#include "OpenSHC/Map/Navigation/DirectionAlgorithmState.func.hpp" +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Map/Units/UnitLogicState.hpp" +#include "OpenSHC/Map/Units/UnitType.hpp" + +#include "OpenSHC/Globals/DAT_DirectionAlgorithmState.hpp" +#include "OpenSHC/Globals/DAT_EntityState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Map::Units::UnitLogicState; + using OpenSHC::Map::Units::UnitType; + + // FUNCTION: STRONGHOLDCRUSADER 0x00537880 + int UnitsState::findNearestShootableDeer(int unitID) + { + for (int _minimumDistance = 20;; _minimumDistance = 5) { + int _bestDistance = 100000; + int _bestUnitID = 0; + for (int _deerUnitID = 1; _deerUnitID < (int)this->maxUnitCount; ++_deerUnitID) { + if (this->units[_deerUnitID].logicalState != OpenSHC::Map::Units::ULS_NORMAL) { + continue; + } + if (this->units[_deerUnitID].dying != 0) { + continue; + } + if (this->units[_deerUnitID].owner != 0) { + continue; + } + if (this->units[_deerUnitID].unitType != OpenSHC::Map::Units::UT_ANTELOPESHDEER) { + continue; + } + MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::DirectionAlgorithmState_Func::setAxisBasedDistanceResult, + DAT_DirectionAlgorithmState::ptr)(this->units[unitID].x, this->units[unitID].y, + this->units[_deerUnitID].x, this->units[_deerUnitID].y); + if (DAT_DirectionAlgorithmState::instance.distanceHigh <= _minimumDistance) { + continue; + } + if (DAT_DirectionAlgorithmState::instance.distanceHigh <= 0x35 + && MACRO_CALL_MEMBER(OpenSHC::Map::Entities::EntityState_Func::arrowShootingRelated, + DAT_EntityState::ptr)(this->units[unitID].microXPosition, + this->units[unitID].microYPosition, + this->units[unitID].buildingHeight + 0x1e + this->units[unitID].terrainOrClimbHeight, + this->units[_deerUnitID].microXPosition, this->units[_deerUnitID].microYPosition, + this->units[_deerUnitID].terrainOrClimbHeight + 0x1a + + this->units[_deerUnitID].buildingHeight) + - 1U + >= 0x1b0) { + continue; + } + if (DAT_DirectionAlgorithmState::instance.distanceHigh < _bestDistance) { + _bestDistance = DAT_DirectionAlgorithmState::instance.distanceHigh; + _bestUnitID = _deerUnitID; + } + } + if (_bestUnitID != 0) { + return _bestUnitID; + } + if (_minimumDistance != 20) { + return 0; + } + } + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 1609c819a..2dc6bc59f 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -51241,7 +51241,7 @@ SHC_3BB0A8C1_0x005377F0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00537840 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x00537880 | 0.0% | Pending +SHC_3BB0A8C1_0x00537880 | 28.6% | retry loop shape differs SHC_3BB0A8C1_0x005378D0 | 0.0% | Pending From 75162a700190ad0400cd480e3f709fab2a63c3f0 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:46 +0200 Subject: [PATCH 133/299] reimplement: SHC_3BB0A8C1_0x00535A30 67.74% call+reg alloc differs --- .../Units/UnitsState/createUnitSelection.cpp | 67 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/createUnitSelection.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/createUnitSelection.cpp b/src/OpenSHC/Map/Units/UnitsState/createUnitSelection.cpp new file mode 100644 index 000000000..b23fb58db --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/createUnitSelection.cpp @@ -0,0 +1,67 @@ +#include "OpenSHC/IO/LowLevelMemory.func.hpp" +#include "OpenSHC/Map/Units/TribesState.func.hpp" +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Synchrony/GameSynchronyState.func.hpp" +#include "OpenSHC/Commands/GameCommandType.hpp" +#include "OpenSHC/Game/GameMode.hpp" +#include "OpenSHC/Map/Units/UnitLogicState.hpp" + +#include "OpenSHC/Globals/DAT_CurrentUnitSlotID.hpp" +#include "OpenSHC/Globals/DAT_GameSynchronyState.hpp" +#include "OpenSHC/Globals/DAT_LowLevelMemory.hpp" +#include "OpenSHC/Globals/DAT_TribesState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Commands::GameCommandType; + using OpenSHC::Game::GameMode; + using OpenSHC::Map::Units::UnitLogicState; + + // FUNCTION: STRONGHOLDCRUSADER 0x00535A30 + int UnitsState::createUnitSelection() + { + /* clear selected units */ + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 400, '\0', this->selectedUnitsBitFlags); + int _selectedCount = 0; + for (DAT_CurrentUnitSlotID::instance = 1; (int)DAT_CurrentUnitSlotID::instance < (int)this->maxUnitCount; + DAT_CurrentUnitSlotID::instance = DAT_CurrentUnitSlotID::instance + 1) { + if (this->units[DAT_CurrentUnitSlotID::instance].logicalState != OpenSHC::Map::Units::ULS_NORMAL) { + continue; + } + if (this->units[DAT_CurrentUnitSlotID::instance].dying != 0) { + continue; + } + if (this->units[DAT_CurrentUnitSlotID::instance].owner + != DAT_GameSynchronyState::instance.currentPlayerSlotID) { + continue; + } + if (this->units[DAT_CurrentUnitSlotID::instance].isSelected == 0) { + continue; + } + if (this->units[DAT_CurrentUnitSlotID::instance].ifSelectedThenPlayerID + == DAT_GameSynchronyState::instance.currentPlayerSlotID + && DAT_GameSynchronyState::instance.currentGameMode == OpenSHC::Game::GM_SOLITARY) { + continue; + } + MACRO_CALL_MEMBER(OpenSHC::Map::Units::TribesState_Func::addUnitToSelected, DAT_TribesState::ptr)( + DAT_CurrentUnitSlotID::instance); + _selectedCount = _selectedCount + 1; + } + if (_selectedCount == 0) { + return 0; + } + DAT_TribesState::instance.DAT_CurrentTribeID + = MACRO_CALL_MEMBER(OpenSHC::Map::Units::TribesState_Func::getAvailableTribeID, DAT_TribesState::ptr)( + DAT_GameSynchronyState::instance.currentPlayerSlotID); + DAT_GameSynchronyState::instance.DAT_GameCommandParam0 = DAT_TribesState::instance.DAT_CurrentTribeID; + MACRO_CALL_MEMBER(OpenSHC::Synchrony::GameSynchronyState_Func::queueCommand, DAT_GameSynchronyState::ptr)( + OpenSHC::Commands::GCT_UNITS_SELECT); + return _selectedCount; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 2dc6bc59f..a87d04378 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -51097,7 +51097,7 @@ SHC_3BB0A8C1_0x00535980 | 100.0% | Reimplemented SHC_3BB0A8C1_0x005359C0 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x00535A30 | 0.0% | Pending +SHC_3BB0A8C1_0x00535A30 | 67.7% | call+reg alloc differs SHC_3BB0A8C1_0x00535B00 | 61.8% | call+reg alloc differs From 96cad7bb61d317333f2f922572d9d4328bf71097 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:46 +0200 Subject: [PATCH 134/299] reimplement: SHC_3BB0A8C1_0x00530500 100.00% Reimplemented --- ...DisappearAndSwapAllOtherUnitsOwnership.cpp | 72 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/makeCourtMemberUnitsDisappearAndSwapAllOtherUnitsOwnership.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/makeCourtMemberUnitsDisappearAndSwapAllOtherUnitsOwnership.cpp b/src/OpenSHC/Map/Units/UnitsState/makeCourtMemberUnitsDisappearAndSwapAllOtherUnitsOwnership.cpp new file mode 100644 index 000000000..305e2eb2e --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/makeCourtMemberUnitsDisappearAndSwapAllOtherUnitsOwnership.cpp @@ -0,0 +1,72 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Map/Units/States/UnitState.hpp" +#include "OpenSHC/Map/Units/UnitLogicState.hpp" +#include "OpenSHC/Map/Units/UnitType.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Map::Units::UnitLogicState; + using OpenSHC::Map::Units::UnitType; + using OpenSHC::Map::Units::States::UnitState; + + // FUNCTION: STRONGHOLDCRUSADER 0x00530500 + void UnitsState::makeCourtMemberUnitsDisappearAndSwapAllOtherUnitsOwnership( + int firstPlayerID, int secondPlayerID) + { + for (int unitID = 1; unitID < 2500; ++unitID) { + if (this->units[unitID].logicalState != OpenSHC::Map::Units::ULS_NORMAL) { + continue; + } + if (this->units[unitID].dying != 0) { + continue; + } + if (this->units[unitID].isStalked != 0) { + switch (this->units[unitID].unitType) { + case OpenSHC::Map::Units::UT_QUARRYOX: + case OpenSHC::Map::Units::UT_COW: + case OpenSHC::Map::Units::UT_HUNTERDOG: + case OpenSHC::Map::Units::UT_CHICKEN: + case OpenSHC::Map::Units::UT_MOTHER: + case OpenSHC::Map::Units::UT_CHILD: + case OpenSHC::Map::Units::UT_JUGGLER: + case OpenSHC::Map::Units::UT_FIREEATER: + break; + default: + continue; + } + } + if (this->units[unitID].owner == firstPlayerID) { + if (this->units[unitID].unitType == OpenSHC::Map::Units::UT_LORD) { + this->units[unitID].state.generic = OpenSHC::Map::Units::States::US_DISAPPEAR; + } else if (this->units[unitID].unitType == OpenSHC::Map::Units::UT_LADY) { + this->units[unitID].state.generic = OpenSHC::Map::Units::States::US_DISAPPEAR; + } else if (this->units[unitID].unitType == OpenSHC::Map::Units::UT_JESTER) { + this->units[unitID].state.generic = OpenSHC::Map::Units::States::US_DISAPPEAR; + } else { + this->units[unitID].owner = (short)secondPlayerID; + if (this->units[unitID].isStalked == 0 || this->units[unitID].calculatedOwnerPlayerIndex != 0) { + this->units[unitID].calculatedOwnerPlayerIndex = secondPlayerID; + } + } + } else if (this->units[unitID].owner == secondPlayerID) { + if (this->units[unitID].unitType == OpenSHC::Map::Units::UT_LORD) { + this->units[unitID].state.generic = OpenSHC::Map::Units::States::US_DISAPPEAR; + } else if (this->units[unitID].unitType == OpenSHC::Map::Units::UT_LADY) { + this->units[unitID].state.generic = OpenSHC::Map::Units::States::US_DISAPPEAR; + } else if (this->units[unitID].unitType == OpenSHC::Map::Units::UT_JESTER) { + this->units[unitID].state.generic = OpenSHC::Map::Units::States::US_DISAPPEAR; + } else { + this->units[unitID].owner = (short)firstPlayerID; + if (this->units[unitID].isStalked == 0 || this->units[unitID].calculatedOwnerPlayerIndex != 0) { + this->units[unitID].calculatedOwnerPlayerIndex = firstPlayerID; + } + } + } + } + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index a87d04378..716a3c558 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -49501,7 +49501,7 @@ SHC_3BB0A8C1_0x005304F4 | 0.0% | Pending SHC_3BB0A8C1_0x005304F5 | 0.0% | Pending -SHC_3BB0A8C1_0x00530500 | 0.0% | Pending +SHC_3BB0A8C1_0x00530500 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00530608 | 0.0% | Pending From eae5f1805e41b77c041ab988bc3c01eccc8cc8ef Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:46 +0200 Subject: [PATCH 135/299] reimplement: SHC_3BB0A8C1_0x0052FF80 67.53% orig caches dir in locals --- .../setUnitFacingDirectionBasedOnBuilding.cpp | 64 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/setUnitFacingDirectionBasedOnBuilding.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/setUnitFacingDirectionBasedOnBuilding.cpp b/src/OpenSHC/Map/Units/UnitsState/setUnitFacingDirectionBasedOnBuilding.cpp new file mode 100644 index 000000000..01a44ea62 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/setUnitFacingDirectionBasedOnBuilding.cpp @@ -0,0 +1,64 @@ +#include "OpenSHC/Map/Navigation/DirectionAlgorithmState.func.hpp" +#include "OpenSHC/Map/Units/UnitsState.func.hpp" + +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_DirectionAlgorithmState.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + // FUNCTION: STRONGHOLDCRUSADER 0x0052FF80 + uint UnitsState::setUnitFacingDirectionBasedOnBuilding(int unitID, int buildingID) + { + if (buildingID == 0) { + return 0; + } + short _previousFacingDirection = this->units[unitID].facingDirection; + MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::DirectionAlgorithmState_Func::calculatePreferredRelativeOrientation, + DAT_DirectionAlgorithmState::ptr)(this->units[unitID].x, this->units[unitID].y, + (short)DAT_BuildingsState::instance.buildings[buildingID].x, + (short)DAT_BuildingsState::instance.buildings[buildingID].y); + if (DAT_DirectionAlgorithmState::instance.orientation == 15) { + return 0; + } + if (this->units[unitID].facingDirection == DAT_DirectionAlgorithmState::instance.orientation) { + return 0; + } + int _clockwiseSteps + = DAT_DirectionAlgorithmState::instance.orientation - this->units[unitID].facingDirection; + if (_clockwiseSteps < 0) { + _clockwiseSteps = _clockwiseSteps + 8; + } + int _counterClockwiseSteps + = this->units[unitID].facingDirection - DAT_DirectionAlgorithmState::instance.orientation; + if (_counterClockwiseSteps < 0) { + _counterClockwiseSteps = _counterClockwiseSteps + 8; + } + if (_counterClockwiseSteps < _clockwiseSteps) { + this->units[unitID].facingDirection = this->units[unitID].facingDirection - 1; + } else { + this->units[unitID].facingDirection = this->units[unitID].facingDirection + 1; + } + if (this->units[unitID].facingDirection < 0) { + this->units[unitID].facingDirection = this->units[unitID].facingDirection + 8; + } + if (this->units[unitID].facingDirection > 7) { + this->units[unitID].facingDirection = this->units[unitID].facingDirection - 8; + } + this->units[unitID].facingDirectionMapOrientationCorrected = this->units[unitID].facingDirection; + this->units[unitID].facingDirectionMapOrientationCorrected + = this->units[unitID].facingDirectionMapOrientationCorrected + - (short)DAT_TileMapState::instance.mapOrientation; + if (this->units[unitID].facingDirectionMapOrientationCorrected < 0) { + this->units[unitID].facingDirectionMapOrientationCorrected + = this->units[unitID].facingDirectionMapOrientationCorrected + 8; + } + return (uint)(_previousFacingDirection != this->units[unitID].facingDirection); + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 716a3c558..c6be4c769 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -49359,7 +49359,7 @@ SHC_3BB0A8C1_0x0052FE00 | 84.8% | reg alloc differs SHC_3BB0A8C1_0x0052FE90 | 81.9% | orig caches dir in locals -SHC_3BB0A8C1_0x0052FF80 | 0.0% | Pending +SHC_3BB0A8C1_0x0052FF80 | 67.5% | orig caches dir in locals SHC_3BB0A8C1_0x00530080 | 100.0% | Reimplemented From 7fec45d6ad499c637d395d75d2e42368fcb7f498 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:47 +0200 Subject: [PATCH 136/299] reimplement: SHC_3BB0A8C1_0x0054C610 72.73% call+reg alloc differs --- .../Units/UnitsState/moveToFreeTileNearby.cpp | 57 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/moveToFreeTileNearby.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/moveToFreeTileNearby.cpp b/src/OpenSHC/Map/Units/UnitsState/moveToFreeTileNearby.cpp new file mode 100644 index 000000000..e878b1161 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/moveToFreeTileNearby.cpp @@ -0,0 +1,57 @@ +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Map/Units/States/UnitState.hpp" +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +#include "OpenSHC/Globals/DAT_CurrentUnitSlotID.hpp" +#include "OpenSHC/Globals/DAT_PathFindingState.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Map::Units::States::UnitState; + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x0054C610 + BOOLEnum UnitsState::moveToFreeTileNearby(int unitID) + { + if ((DAT_TileMapState::instance.LogicLayer[this->units[unitID].tile] & 0x30U) != 0) { + if (MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::findDirectNeighbourWalkableTile, + DAT_PathFindingState::ptr)(this->units[unitID].x, this->units[unitID].y) + != FALSE) { + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::setPositionOfUnit, this)(unitID, + DAT_PathFindingState::instance.ALG_ResultX, DAT_PathFindingState::instance.ALG_ResultY, + DAT_TileMapState::instance.HeightLayer[DAT_PathFindingState::instance.ALG_ResultTile]); + } + return FALSE; + } + if ((short)DAT_TileMapState::instance.UnitLayer[this->units[unitID].tile] == unitID) { + return FALSE; + } + if ((DAT_TileMapState::instance.LogicLayer[this->units[unitID].tile] & 0x100U) == 0) { + /* not a wall tower or gatehouse */ + MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::PathFindingState_Func::findPathableTileWithoutUnitWithBuildingAtXY, + DAT_PathFindingState::ptr)(-1, this->units[unitID].x, this->units[unitID].y); + } else { + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::findFreeTileOnDefensiveStructure, + DAT_PathFindingState::ptr)(-1, this->units[unitID].x, this->units[unitID].y); + } + if (DAT_PathFindingState::instance.ALG_ResultTile == 0) { + return FALSE; + } + if (MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::setDestinationForUnit, this)( + unitID, DAT_PathFindingState::instance.ALG_ResultX, DAT_PathFindingState::instance.ALG_ResultY, 0) + == FALSE) { + return FALSE; + } + this->units[DAT_CurrentUnitSlotID::instance].state.generic + = OpenSHC::Map::Units::States::US_MOVE_TO_DESTINATION; + return TRUE; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index c6be4c769..f10b0aea2 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -62507,7 +62507,7 @@ SHC_3BB0A8C1_0x0054C1C0 | 0.0% | Pending SHC_3BB0A8C1_0x0054C4F0 | 14.0% | orig walks matrix row ptr -SHC_3BB0A8C1_0x0054C610 | 0.0% | Pending +SHC_3BB0A8C1_0x0054C610 | 72.7% | call+reg alloc differs SHC_3BB0A8C1_0x0054C710 | 0.0% | Pending From 394e335ddea1266c0c5742a421610d2678ef42bd Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:47 +0200 Subject: [PATCH 137/299] reimplement: SHC_3BB0A8C1_0x005360A0 90.54% orig unrolls inner loop x5 --- .../UnitsState/isUnitShortcutAvailable.cpp | 62 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/isUnitShortcutAvailable.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/isUnitShortcutAvailable.cpp b/src/OpenSHC/Map/Units/UnitsState/isUnitShortcutAvailable.cpp new file mode 100644 index 000000000..6a88fc898 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/isUnitShortcutAvailable.cpp @@ -0,0 +1,62 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Map/Units/UnitLogicState.hpp" +#include "OpenSHC/UI/Enums/BuildingsAndStatusMenuTabType.hpp" +#include "OpenSHC/UI/Enums/MenuViewType.hpp" +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +#include "OpenSHC/Globals/DAT_GameCore.hpp" +#include "OpenSHC/Globals/DAT_GameState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Map::Units::UnitLogicState; + using OpenSHC::UI::Enums::BuildingsAndStatusMenuTabType; + using OpenSHC::UI::Enums::MenuViewType; + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x005360A0 + BOOLEnum UnitsState::isUnitShortcutAvailable(int unitHotKeyNumber) + { + if (DAT_GameCore::instance.currentMenuViewType != OpenSHC::UI::Enums::MVT_BUILD_MENU) { + return FALSE; + } + if (DAT_GameCore::instance.activeMenuTab.tabType != OpenSHC::UI::Enums::BASMTT_SIEGETENT_BATTERINGRAM + && DAT_GameCore::instance.activeMenuTab.tabType != OpenSHC::UI::Enums::BASMTT_SIEGETENT_SHIELD) { + return FALSE; + } + for (int unitID = 1; unitID < (int)this->maxUnitCount; ++unitID) { + if (this->units[unitID].logicalState != OpenSHC::Map::Units::ULS_NORMAL) { + continue; + } + if (this->units[unitID].dying != 0) { + continue; + } + if (this->units[unitID].isSelected == 0) { + for (int i = 0; i < 2500; ++i) { + /* unitID is listed in this hotkey unit list and not selected */ + if (DAT_GameState::instance.hotkeyTribes[unitHotKeyNumber].units[i].id == unitID) { + return FALSE; + } + } + continue; + } + int _isListed = 0; + for (int i = 0; i < 2500; ++i) { + if (DAT_GameState::instance.hotkeyTribes[unitHotKeyNumber].units[i].id == unitID) { + _isListed = 1; + } + } + /* unitID is listed in this hotkey unit list and is selected */ + if (_isListed == 0) { + return FALSE; + } + } + /* There is no unitID to be found in a normal non-dead state that is selectable */ + return TRUE; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index f10b0aea2..8324f732f 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -51109,7 +51109,7 @@ SHC_3BB0A8C1_0x00535E20 | 0.0% | Pending SHC_3BB0A8C1_0x00535FD0 | 88.9% | orig walks hotkey ptr -SHC_3BB0A8C1_0x005360A0 | 0.0% | Pending +SHC_3BB0A8C1_0x005360A0 | 90.5% | orig unrolls inner loop x5 SHC_3BB0A8C1_0x00536190 | 72.4% | incr scheduled before call From e1ce37800297eadffae7fa874f00e40b7e1241d1 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:48 +0200 Subject: [PATCH 138/299] reimplement: SHC_3BB0A8C1_0x0053E900 87.04% reg alloc differs --- .../Units/UnitsState/setPositionOfUnit.cpp | 39 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/setPositionOfUnit.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/setPositionOfUnit.cpp b/src/OpenSHC/Map/Units/UnitsState/setPositionOfUnit.cpp new file mode 100644 index 000000000..1c52ff938 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/setPositionOfUnit.cpp @@ -0,0 +1,39 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" + +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + // FUNCTION: STRONGHOLDCRUSADER 0x0053E900 + void UnitsState::setPositionOfUnit(int unitID, uint x, uint y, undefined4 height) + { + if (x >= 400 || y >= 400) { + return; + } + /* the 400x400 map of placeable tiles at 0x021AEC98 */ + if (*(char*)(y * 400 + 0x21aec98 + x) == '\0') { + return; + } + this->units[unitID].currentIndexInPathPlan = 0; + this->units[unitID].tunnelerFinishedDigging = 0; + this->units[unitID].field105_0xe8 = 0; + this->units[unitID].movementRelated = 8; + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::setupUnitSharingCurrentTilePosition, this)(unitID); + this->units[unitID].microXPosition = (short)x * 8 + 4; + this->units[unitID].microYPosition = (short)y * 8 + 4; + this->units[unitID].terrainOrClimbHeight = (short)height; + this->units[unitID].mimicCurrentXPosition = (short)x; + this->units[unitID].x = (short)x; + this->units[unitID].mimicCurrentYPosition = (short)y; + this->units[unitID].y = (short)y; + this->units[unitID].tile + = (short)x + DAT_ViewportRenderState::instance.translationMatrix[(short)y].addXgetTile; + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::commitPendingUnitPosition, this)(unitID); + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::updateMicroPosition, this)(unitID); + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 8324f732f..c9471776f 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -60097,7 +60097,7 @@ SHC_3BB0A8C1_0x0053E870 | 85.7% | reg alloc differs SHC_3BB0A8C1_0x0053E8D0 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x0053E900 | 0.0% | Pending +SHC_3BB0A8C1_0x0053E900 | 87.0% | reg alloc differs SHC_3BB0A8C1_0x0053E9F0 | 56.8% | orig caches x/y in locals From 25ca1139d545ca401b52eeb4b269af99cc6f4a0b Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:48 +0200 Subject: [PATCH 139/299] reimplement: SHC_3BB0A8C1_0x005350B0 100.00% Reimplemented --- .../selectAllUnitsOfTypeForPlayer.cpp | 36 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/selectAllUnitsOfTypeForPlayer.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/selectAllUnitsOfTypeForPlayer.cpp b/src/OpenSHC/Map/Units/UnitsState/selectAllUnitsOfTypeForPlayer.cpp new file mode 100644 index 000000000..a170ef1c2 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/selectAllUnitsOfTypeForPlayer.cpp @@ -0,0 +1,36 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Map/Units/States/UnitState.hpp" +#include "OpenSHC/Map/Units/UnitLogicState.hpp" + +#include "OpenSHC/Globals/DAT_CurrentUnitSlotID.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Map::Units::UnitLogicState; + using OpenSHC::Map::Units::States::UnitState; + + // FUNCTION: STRONGHOLDCRUSADER 0x005350B0 + void UnitsState::selectAllUnitsOfTypeForPlayer(int playerID, int unitType) + { + this->totalUnitsInSelection = 0; + for (DAT_CurrentUnitSlotID::instance = 1; (int)DAT_CurrentUnitSlotID::instance < (int)this->maxUnitCount; + DAT_CurrentUnitSlotID::instance = DAT_CurrentUnitSlotID::instance + 1) { + if (this->units[DAT_CurrentUnitSlotID::instance].logicalState == OpenSHC::Map::Units::ULS_NORMAL + && this->units[DAT_CurrentUnitSlotID::instance].dying == 0 + && this->units[DAT_CurrentUnitSlotID::instance].unknownTestAgainst0_2 == 0 + && this->units[DAT_CurrentUnitSlotID::instance].state.generic + != OpenSHC::Map::Units::States::US_JESTER_ROAM_TO + && (short)this->units[DAT_CurrentUnitSlotID::instance].unitType == unitType + && this->units[DAT_CurrentUnitSlotID::instance].drawX != 0 + && this->units[DAT_CurrentUnitSlotID::instance].owner == playerID) { + this->units[DAT_CurrentUnitSlotID::instance].isSelected = 1; + this->totalUnitsInSelection = this->totalUnitsInSelection + 1; + } + } + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index c9471776f..f800daca1 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -50853,7 +50853,7 @@ SHC_3BB0A8C1_0x00534EE0 | 0.0% | Pending SHC_3BB0A8C1_0x00534F50 | 0.0% | Pending -SHC_3BB0A8C1_0x005350B0 | 0.0% | Pending +SHC_3BB0A8C1_0x005350B0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00535150 | 100.0% | Reimplemented From e84180473d1dab152fcd0029523121ce3a9d1fa3 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:48 +0200 Subject: [PATCH 140/299] reimplement: SHC_3BB0A8C1_0x0053D900 68.75% orig caches x/y in locals --- .../Map/Units/UnitsState/exitLadder.cpp | 35 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/exitLadder.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/exitLadder.cpp b/src/OpenSHC/Map/Units/UnitsState/exitLadder.cpp new file mode 100644 index 000000000..7d0f0fdf0 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/exitLadder.cpp @@ -0,0 +1,35 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" + +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + // FUNCTION: STRONGHOLDCRUSADER 0x0053D900 + void UnitsState::exitLadder(int unitID) + { + int _previousTile = this->units[unitID].field42_0x60; + this->units[unitID].vanish = 0; + this->units[unitID].usingTeleport = 0; + this->units[unitID].field203_0x35c = 0; + this->units[unitID].field43_0x64 = 0; + this->units[unitID].movementRelated = 8; + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::setupUnitSharingTileIDs, this)( + unitID, _previousTile); + this->units[unitID].field42_0x60 = 0; + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::setupUnitSharingCurrentTilePosition, this)(unitID); + this->units[unitID].y = this->units[unitID].mimicCurrentYPosition; + this->units[unitID].x = this->units[unitID].mimicCurrentXPosition; + this->units[unitID].microYPosition = this->units[unitID].mimicCurrentYPosition * 8 + 4; + this->units[unitID].tile = this->units[unitID].mimicCurrentXPosition + + DAT_ViewportRenderState::instance.translationMatrix[this->units[unitID].mimicCurrentYPosition] + .addXgetTile; + this->units[unitID].microXPosition = this->units[unitID].mimicCurrentXPosition * 8 + 4; + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::updateMicroPosition, this)(unitID); + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::commitPendingUnitPosition, this)(unitID); + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index f800daca1..5eeec4626 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -60017,7 +60017,7 @@ SHC_3BB0A8C1_0x0053D3D0 | 0.0% | Pending SHC_3BB0A8C1_0x0053D850 | 69.8% | reg alloc differs -SHC_3BB0A8C1_0x0053D900 | 0.0% | Pending +SHC_3BB0A8C1_0x0053D900 | 68.8% | orig caches x/y in locals SHC_3BB0A8C1_0x0053D9C0 | 0.0% | Pending From 829badbbfaad1c024ecbfa9578a671fde9626c90 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:49 +0200 Subject: [PATCH 141/299] reimplement: SHC_3BB0A8C1_0x0052E830 89.47% orig walks unit ptr --- .../UnitsState/assignPeasantToBuilding.cpp | 71 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/assignPeasantToBuilding.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/assignPeasantToBuilding.cpp b/src/OpenSHC/Map/Units/UnitsState/assignPeasantToBuilding.cpp new file mode 100644 index 000000000..6af31118f --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/assignPeasantToBuilding.cpp @@ -0,0 +1,71 @@ +#include "OpenSHC/Map/Buildings/BuildingsState.func.hpp" +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Map/Units/States/UnitState.hpp" +#include "OpenSHC/Map/Units/UnitLogicState.hpp" +#include "OpenSHC/Map/Units/UnitType.hpp" +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Map::Units::UnitLogicState; + using OpenSHC::Map::Units::UnitType; + using OpenSHC::Map::Units::States::UnitState; + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x0052E830 + int UnitsState::assignPeasantToBuilding(UnitType unitType, int buildingID, int playerID, int workerIndex) + { + /* Finds a valid peasant, changes them into specified workertype and assignes + them to building */ + for (int unitID = 1; unitID < (int)this->maxUnitCount; ++unitID) { + if (this->units[unitID].owner != playerID) { + continue; + } + if (this->units[unitID].unitType != OpenSHC::Map::Units::UT_PEASANT) { + continue; + } + if (this->units[unitID].dying != 0) { + continue; + } + if (this->units[unitID].logicalState != OpenSHC::Map::Units::ULS_NORMAL) { + continue; + } + if (this->units[unitID].state.generic == OpenSHC::Map::Units::States::US_RELOAD_WEAPONUnk) { + continue; + } + if (this->units[unitID].state.generic == OpenSHC::Map::Units::States::US_AIM_WEAPONUnk) { + continue; + } + if (this->units[unitID].state.generic == OpenSHC::Map::Units::States::US_JESTER_ROAM_TO) { + continue; + } + if (this->units[unitID].state.generic == OpenSHC::Map::Units::States::US_MELEE_ATTACK) { + continue; + } + MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::determineBuildingEntranceFromKeepArea, + DAT_BuildingsState::ptr)(buildingID, workerIndex + 1, FALSE); + this->units[unitID].workplaceBuildingID_1 = (short)buildingID; + this->units[unitID].workplaceBuildingUID = DAT_BuildingsState::instance.buildings[buildingID].uid; + this->units[unitID].targetX_2 = DAT_BuildingsState::instance.buildings[buildingID].buildingEntryX; + this->units[unitID].unitTypeToChangeInto = (undefined2)unitType; + this->units[unitID].targetY_2 = DAT_BuildingsState::instance.buildings[buildingID].buildingEntryY; + this->units[unitID].state_2 = 0; + MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::determineBuildingEntranceFromKeepArea, + DAT_BuildingsState::ptr)(buildingID, 1, FALSE); + this->units[unitID].state.generic = OpenSHC::Map::Units::States::US_JESTER_ROAM_TO; + this->units[unitID].disappearFadeAlphaCountdown = 0; + this->units[unitID].engineerManningSiegeStateRef_checkType = 1; + this->units[unitID].cachedState = OpenSHC::Map::Units::States::US_DETERMINE_NEXT_STATEUnk; + this->units[unitID].isDisappearingUnk = 1; + return unitID; + } + return 0; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 5eeec4626..e0d66b57a 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -49305,7 +49305,7 @@ SHC_3BB0A8C1_0x0052E1A0 | 0.0% | Pending SHC_3BB0A8C1_0x0052E7B0 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x0052E830 | 0.0% | Pending +SHC_3BB0A8C1_0x0052E830 | 89.5% | orig walks unit ptr SHC_3BB0A8C1_0x0052E960 | 0.0% | Pending From 642fc6f530e90716d0b49081561bdd312e85e7d9 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:49 +0200 Subject: [PATCH 142/299] reimplement: SHC_3BB0A8C1_0x00537AA0 38.92% orig walks unit ptr --- .../findClosestAnimalStoreResult.cpp | 80 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/findClosestAnimalStoreResult.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/findClosestAnimalStoreResult.cpp b/src/OpenSHC/Map/Units/UnitsState/findClosestAnimalStoreResult.cpp new file mode 100644 index 000000000..7b3ab6d8e --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/findClosestAnimalStoreResult.cpp @@ -0,0 +1,80 @@ +#include "OpenSHC/Map/Navigation/DirectionAlgorithmState.func.hpp" +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Map/Units/States/UnitState.hpp" +#include "OpenSHC/Map/Units/UnitLogicState.hpp" +#include "OpenSHC/Map/Units/UnitType.hpp" +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +#include "OpenSHC/Globals/DAT_DirectionAlgorithmState.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Map::Units::UnitLogicState; + using OpenSHC::Map::Units::UnitType; + using OpenSHC::Map::Units::States::UnitState; + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x00537AA0 + int UnitsState::findClosestAnimalStoreResult(int maxDistance, BOOLEnum excludeCows, uint x, uint y) + { + if (x > 399 || y > 399) { + return 0; + } + /* the 400x400 map of placeable tiles at 0x021AEC98 */ + if (*(char*)(y * 400 + 0x21aec98 + x) == '\0') { + return 0; + } + ushort _areaOfOrigin + = DAT_TileMapState::instance + .PathConnectionLayer[DAT_ViewportRenderState::instance.translationMatrix[y].addXgetTile + x]; + this->unusedUnitIDArrayIndex = 0; + int _bestScore = 10000; + int _bestUnitID = 0; + for (int unitID = 1; unitID < (int)this->maxUnitCount; ++unitID) { + if (this->units[unitID].logicalState != OpenSHC::Map::Units::ULS_NORMAL) { + continue; + } + if (this->units[unitID].dying != 0) { + continue; + } + if (this->units[unitID].unknownTestAgainst0_2 != 0) { + continue; + } + if (this->units[unitID].state.generic == OpenSHC::Map::Units::States::US_MELEE_ATTACK) { + continue; + } + if (excludeCows == FALSE) { + if (this->units[unitID].unitType != OpenSHC::Map::Units::UT_ANTELOPESHDEER + && this->units[unitID].unitType != OpenSHC::Map::Units::UT_RABBIT + && this->units[unitID].unitType != OpenSHC::Map::Units::UT_COW) { + continue; + } + } else if (this->units[unitID].isStalked != 0) { + continue; + } + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::DirectionAlgorithmState_Func::setAxisBasedDistanceResult, + DAT_DirectionAlgorithmState::ptr)(x, y, this->units[unitID].x, this->units[unitID].y); + if (DAT_DirectionAlgorithmState::instance.distanceHigh > maxDistance) { + continue; + } + if (DAT_TileMapState::instance.PathConnectionLayer[this->units[unitID].tile] != _areaOfOrigin) { + continue; + } + this->unusedUnitIDArray[this->unusedUnitIDArrayIndex] = (short)unitID; + this->unusedUnitIDArrayIndex = this->unusedUnitIDArrayIndex + 1; + int _score = DAT_DirectionAlgorithmState::instance.distanceHigh + this->units[unitID].huntedBy * 3; + if (_score < _bestScore) { + _bestScore = _score; + _bestUnitID = unitID; + } + } + return _bestUnitID; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index e0d66b57a..1792271e9 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -51249,7 +51249,7 @@ SHC_3BB0A8C1_0x005378F0 | 0.0% | Pending SHC_3BB0A8C1_0x00537A00 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x00537AA0 | 0.0% | Pending +SHC_3BB0A8C1_0x00537AA0 | 38.9% | orig walks unit ptr SHC_3BB0A8C1_0x00537B20 | 0.0% | Pending From 43001ca4e5aa23c78240f26049a8152c357a9bf6 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:49 +0200 Subject: [PATCH 143/299] reimplement: SHC_3BB0A8C1_0x005300B0 25.00% orig caches rng in local --- .../Units/UnitsState/playHurtSFXForUnit.cpp | 77 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 78 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/playHurtSFXForUnit.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/playHurtSFXForUnit.cpp b/src/OpenSHC/Map/Units/UnitsState/playHurtSFXForUnit.cpp new file mode 100644 index 000000000..b56891291 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/playHurtSFXForUnit.cpp @@ -0,0 +1,77 @@ +#include "OpenSHC/Audio/SFX/SFXState.func.hpp" +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/DE/SHCDE/eSFX.hpp" +#include "OpenSHC/Map/Units/UnitType.hpp" + +#include "OpenSHC/Globals/DAT_SFXState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::DE::SHCDE::eSFX; + using OpenSHC::Map::Units::UnitType; + + // FUNCTION: STRONGHOLDCRUSADER 0x005300B0 + void UnitsState::playHurtSFXForUnit(int unitID) + { + if (unitID == 0) { + return; + } + if (this->units[unitID].healthPercentage < 0xb) { + return; + } + if (this->units[unitID].isStalked != 0) { + return; + } + if ((short)this->units[unitID].unitType < 1) { + return; + } + eSFX _sfxOffsetInArray; + if (this->units[unitID].unitType == OpenSHC::Map::Units::UT_S_CATAPULT + || this->units[unitID].unitType == OpenSHC::Map::Units::UT_S_TREBUCHET + || this->units[unitID].unitType == OpenSHC::Map::Units::UT_S_MANGONEL + || this->units[unitID].unitType == OpenSHC::Map::Units::UT_S_BALLISTA + || this->units[unitID].unitType == OpenSHC::Map::Units::UT_S_TOWER + || this->units[unitID].unitType == OpenSHC::Map::Units::UT_S_BATTERINGRAM) { + _sfxOffsetInArray = OpenSHC::DE::SHCDE::FX_ATTACK_WOOD; + } else if (this->units[unitID].unitType == OpenSHC::Map::Units::UT_BREWER + || this->units[unitID].unitType == OpenSHC::Map::Units::UT_TANNER + || this->units[unitID].unitType == OpenSHC::Map::Units::UT_LADY + || this->units[unitID].unitType == OpenSHC::Map::Units::UT_MOTHER + || (this->units[unitID].unitType == OpenSHC::Map::Units::UT_CHILD + && this->units[unitID].spriteID == 0x81)) { + _sfxOffsetInArray = OpenSHC::DE::SHCDE::FX_GIRL_GRUNT; + } else { + if (this->units[unitID].unitType == OpenSHC::Map::Units::UT_S_SHIELD + && this->units[unitID].digTileX__OR__countCurrentlyManningEnginers__OR__forCowsRandomBelow300 + == 0) { + return; + } + if ((this->units[unitID].fixedRng & 7) == 0) { + _sfxOffsetInArray = OpenSHC::DE::SHCDE::FX_BODY_HIT; + } else if ((this->units[unitID].fixedRng & 7) == 1) { + _sfxOffsetInArray = OpenSHC::DE::SHCDE::FX_BODY_HIT2; + } else if ((this->units[unitID].fixedRng & 7) == 2) { + _sfxOffsetInArray = OpenSHC::DE::SHCDE::FX_BODY_HIT3; + } else if ((this->units[unitID].fixedRng & 7) == 3) { + _sfxOffsetInArray = OpenSHC::DE::SHCDE::FX_BODY_HIT4; + } else if ((this->units[unitID].fixedRng & 7) == 4) { + _sfxOffsetInArray = OpenSHC::DE::SHCDE::FX_BODY_HIT5; + } else if ((this->units[unitID].fixedRng & 7) == 5) { + _sfxOffsetInArray = OpenSHC::DE::SHCDE::FX_BODY_HIT6; + } else if ((this->units[unitID].fixedRng & 7) == 6) { + _sfxOffsetInArray = OpenSHC::DE::SHCDE::FX_BODY_HIT7; + } else if ((this->units[unitID].fixedRng & 7) == 7) { + _sfxOffsetInArray = OpenSHC::DE::SHCDE::FX_BODY_HIT8; + } else { + return; + } + } + MACRO_CALL_MEMBER(OpenSHC::Audio::SFX::SFXState_Func::playSFXAtLocation, DAT_SFXState::ptr)( + this->units[unitID].x, this->units[unitID].y, _sfxOffsetInArray); + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 1792271e9..672cbb206 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -49363,7 +49363,7 @@ SHC_3BB0A8C1_0x0052FF80 | 67.5% | orig caches dir in locals SHC_3BB0A8C1_0x00530080 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x005300B0 | 0.0% | Pending +SHC_3BB0A8C1_0x005300B0 | 25.0% | orig caches rng in local SHC_3BB0A8C1_0x005301F0 | 96.0% | reg alloc differs From 0ce7da980a6701785bff6a7cc42ebcf74a764695 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:50 +0200 Subject: [PATCH 144/299] reimplement: SHC_3BB0A8C1_0x0052F0D0 40.96% branch shape differs --- .../recomputeUnitStandingHeight.cpp | 72 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/recomputeUnitStandingHeight.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/recomputeUnitStandingHeight.cpp b/src/OpenSHC/Map/Units/UnitsState/recomputeUnitStandingHeight.cpp new file mode 100644 index 000000000..9300f5011 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/recomputeUnitStandingHeight.cpp @@ -0,0 +1,72 @@ +#include "OpenSHC/Map/Buildings/BuildingsState.func.hpp" +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Map/Buildings/BuildingType.hpp" +#include "OpenSHC/Map/Units/UnitType.hpp" + +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_CurrentUnitSlotID.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Map::Buildings::BuildingType; + using OpenSHC::Map::Units::UnitType; + + // FUNCTION: STRONGHOLDCRUSADER 0x0052F0D0 + void UnitsState::recomputeUnitStandingHeight(int unitID) + { + int _tile = this->units[unitID].tile; + uint _logicFlags = DAT_TileMapState::instance.LogicLayer[_tile]; + int _buildingID = DAT_TileMapState::instance.BuildingLayer[_tile]; + this->units[unitID].buildingHeight = 0; + this->units[unitID].field58_0x84 = 0; + if ((_logicFlags & 0x10010d00) == 0) { + if (_buildingID == 0) { + if (this->units[unitID].wasOnStoneGate != 0) { + this->units[unitID].terrainOrClimbHeight = DAT_TileMapState::instance.HeightLayer[_tile]; + this->units[unitID].wasOnStoneGate = 0; + } + } else if (DAT_BuildingsState::instance.buildings[_buildingID].buildingType + == OpenSHC::Map::Buildings::BT_DRAWBRIDGE) { + this->units[unitID].buildingHeight = 8 - this->units[unitID].terrainOrClimbHeight; + } + } else if ((_logicFlags & 0x800) != 0) { + this->units[unitID].buildingHeight = 0xc; + } else if ((_logicFlags & 0x100) != 0) { + if (_buildingID == 0) { + this->units[unitID].buildingHeight = 4; + } else if (this->units[unitID].unknownCountdown_0x402 == 0) { + this->units[unitID].buildingHeight = 0x28; + } else { + this->units[unitID].buildingHeight = -0x5a; + if (this->units[unitID].terrainOrClimbHeight + -0x5a < 8) { + this->units[unitID].buildingHeight = 0; + } + this->units[unitID].wasOnStoneGate = 1; + } + } else if ((_logicFlags & 0x400) != 0) { + this->units[unitID].buildingHeight = 2; + } else if ((_logicFlags & 0x10000000) != 0) { + if (this->units[unitID].unknownCountdown_0x402 == 0 + && this->units[unitID].unitType != OpenSHC::Map::Units::UT_S_TOWER) { + this->units[unitID].buildingHeight = (short)MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::getBuildingHeightForBuildingID, + DAT_BuildingsState::ptr)(_buildingID); + } + this->units[unitID].field58_0x84 = (short)MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::getBuildingHeightForBuildingID2, + DAT_BuildingsState::ptr)(_buildingID); + this->units[unitID].terrainOrClimbHeight + = DAT_BuildingsState::instance.buildings[_buildingID].terrainHeightUnk; + } + if (this->units[DAT_CurrentUnitSlotID::instance].field306_0x418 != 0) { + this->units[unitID].buildingHeight + = this->units[unitID].buildingHeight + this->units[DAT_CurrentUnitSlotID::instance].field306_0x418; + } + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 672cbb206..41d992a5c 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -49321,7 +49321,7 @@ SHC_3BB0A8C1_0x0052F070 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0052F0A0 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x0052F0D0 | 0.0% | Pending +SHC_3BB0A8C1_0x0052F0D0 | 41.0% | branch shape differs SHC_3BB0A8C1_0x0052F260 | 0.0% | Pending From 6ea07e9e7485b3b2e2c523fbe613e5dbe23c11fc Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:50 +0200 Subject: [PATCH 145/299] reimplement: SHC_3BB0A8C1_0x0052EDC0 48.48% branch shape differs --- .../Map/Units/UnitsState/disbandUnit.cpp | 68 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/disbandUnit.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/disbandUnit.cpp b/src/OpenSHC/Map/Units/UnitsState/disbandUnit.cpp new file mode 100644 index 000000000..6c191e957 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/disbandUnit.cpp @@ -0,0 +1,68 @@ +#include "OpenSHC/Game/GameStateStructures.func.hpp" +#include "OpenSHC/Map/Buildings/BuildingsState.func.hpp" +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Game/GameMode2.hpp" +#include "OpenSHC/Map/Units/States/UnitState.hpp" +#include "OpenSHC/Map/Units/UnitLogicState.hpp" +#include "OpenSHC/Map/Units/UnitType.hpp" +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_GameCore.hpp" +#include "OpenSHC/Globals/DAT_GameState.hpp" +#include "OpenSHC/Globals/DAT_GameSynchronyState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Game::GameMode2; + using OpenSHC::Map::Units::UnitLogicState; + using OpenSHC::Map::Units::UnitType; + using OpenSHC::Map::Units::States::UnitState; + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x0052EDC0 + int UnitsState::disbandUnit(int unitID) + { + if (this->units[unitID].unitType == OpenSHC::Map::Units::UT_E_KNIGHT + && this->units[unitID].horseOriginStablesBuildingIndexUnk != 0) { + if (*(int*)&this->units[unitID].horseOriginStableIDUnk + == DAT_BuildingsState::instance.buildings[this->units[unitID].horseOriginStablesBuildingIndexUnk] + .uid) { + MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::removeTetheredUnitFromBuilding, + DAT_BuildingsState::ptr)(this->units[unitID].horseOriginStablesBuildingIndexUnk, unitID); + } + } + if (DAT_GameCore::instance.gameMode_2 == OpenSHC::Game::GM_SIEGE_THAT) { + UnitTypeShort _unitType = this->units[unitID].unitType; + this->units[unitID].logicalState = OpenSHC::Map::Units::ULS_REMOVE; + /* note &unitID ! */ + int _refund = unitID; + MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::getPriceForDisbandedUnitType, + DAT_BuildingsState::ptr)((UnitType)(short)_unitType, &_refund); + DAT_GameState::instance.playerDataArray[DAT_GameSynchronyState::instance.currentPlayerSlotID] + .startResources[0xf] += _refund; + return DAT_GameSynchronyState::instance.currentPlayerSlotID * 0x39f4 + 0x115c2a0; + } + BOOLEnum _hasCampground = MACRO_CALL_MEMBER(OpenSHC::Game::GameStateStructures_Func::playerHasACampground, + DAT_GameState::ptr)(this->units[unitID].owner); + this->units[unitID].disappearFadeAlphaCountdown = 0; + if (_hasCampground != FALSE) { + this->units[unitID].state_2 = 0; + this->units[unitID].cachedState = OpenSHC::Map::Units::States::US_DETERMINE_NEXT_STATEUnk; + this->units[unitID].unitTypeToChangeInto = OpenSHC::Map::Units::UT_PEASANT; + this->units[unitID].state.generic = OpenSHC::Map::Units::States::US_JESTER_ROAM_TO; + this->units[unitID].engineerManningSiegeStateRef_checkType = 1; + this->units[unitID].isDisappearingUnk = 1; + return 1; + } + this->units[unitID].updateTickTracker = 0; + this->units[unitID].state.generic = OpenSHC::Map::Units::States::US_DISAPPEAR; + this->units[unitID].killedFlagUnk = 1; + return 0; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 41d992a5c..e9421b054 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -49311,7 +49311,7 @@ SHC_3BB0A8C1_0x0052E960 | 0.0% | Pending SHC_3BB0A8C1_0x0052EC10 | 0.0% | Pending -SHC_3BB0A8C1_0x0052EDC0 | 0.0% | Pending +SHC_3BB0A8C1_0x0052EDC0 | 48.5% | branch shape differs SHC_3BB0A8C1_0x0052EED0 | 80.0% | orig caches unitType local From 086c1458f363da8f5f56e8329df5718ef772322a Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:51 +0200 Subject: [PATCH 146/299] reimplement: SHC_3BB0A8C1_0x0053DCC0 14.93% orig caches many locals --- .../setDestinationNearTargetedBuilding.cpp | 58 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/setDestinationNearTargetedBuilding.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/setDestinationNearTargetedBuilding.cpp b/src/OpenSHC/Map/Units/UnitsState/setDestinationNearTargetedBuilding.cpp new file mode 100644 index 000000000..b71d1b87e --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/setDestinationNearTargetedBuilding.cpp @@ -0,0 +1,58 @@ +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Map/Units/States/UnitState.hpp" +#include "OpenSHC/Map/Units/UnitInstructionType.hpp" + +#include "OpenSHC/Globals/DAT_PathFindingState.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Map::Units::UnitInstructionType; + using OpenSHC::Map::Units::States::UnitState; + + // FUNCTION: STRONGHOLDCRUSADER 0x0053DCC0 + undefined4 UnitsState::setDestinationNearTargetedBuilding(int unitID, int param_2) + { + ushort _areaAtUnitTile = DAT_TileMapState::instance.PathConnectionLayer[this->units[unitID].tile]; + DAT_TileMapState::instance.PathConnectionLayer[this->units[unitID].targetedBuildingTile] = _areaAtUnitTile; + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func:: + findFreeSpaceNextToEnemyDefensiveStructureInSameAreaWithinDistance, + DAT_PathFindingState::ptr)(this->units[unitID].targetedBuildingTile, 1, (int*)(short)_areaAtUnitTile, + this->units[unitID].owner, param_2, this->units[unitID].facingDirection); + if (DAT_PathFindingState::instance.searchQueue.destinationsArray[0].tile1 == 0) { + return 0; + } + if (DAT_PathFindingState::instance.searchQueue.destinationsArray[0].tile2OrAHelper == 0) { + return 0; + } + short _destinationY = DAT_ViewportRenderState::instance.tileTranslationMatrix_YComponent + [DAT_PathFindingState::instance.searchQueue.destinationsArray[0].tile1]; + int _destinationX = DAT_PathFindingState::instance.searchQueue.destinationsArray[0].tile1 + - DAT_ViewportRenderState::instance.translationMatrix[_destinationY].addXgetTile; + this->units[unitID].plannedDestinationX = (short)_destinationX; + this->units[unitID].targetingType = (UnitInstructionType)0; + DAT_PathFindingState::instance.notAllAssassinsUnk = 1; + this->units[unitID].plannedDestinationY = _destinationY; + this->units[unitID].state.generic = OpenSHC::Map::Units::States::US_MOVE_TO_DESTINATION; + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::setDestinationForUnit, this)( + unitID, _destinationX, _destinationY, 0); + if (this->units[unitID].field64_0x90 != 0) { + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::changeDestinationByAmount, this)(unitID, 2); + } + short _attackTileY = DAT_ViewportRenderState::instance.tileTranslationMatrix_YComponent + [DAT_PathFindingState::instance.searchQueue.destinationsArray[0].tile2OrAHelper]; + this->units[unitID].attackAtTileY = _attackTileY; + this->units[unitID].targetedBuildingTile + = DAT_PathFindingState::instance.searchQueue.destinationsArray[0].tile2OrAHelper; + this->units[unitID].attackAtTileX = (short)this->units[unitID].targetedBuildingTile + - (short)DAT_ViewportRenderState::instance.translationMatrix[_attackTileY].addXgetTile; + return 1; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index e9421b054..60b341cc2 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -60035,7 +60035,7 @@ SHC_3BB0A8C1_0x0053DCB0 | 0.0% | Pending SHC_3BB0A8C1_0x0053DCB4 | 0.0% | Pending -SHC_3BB0A8C1_0x0053DCC0 | 0.0% | Pending +SHC_3BB0A8C1_0x0053DCC0 | 14.9% | orig caches many locals SHC_3BB0A8C1_0x0053DDD0 | 0.0% | Pending From c1c32fd86a19b6bc919b9c52480455e895195e9d Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:51 +0200 Subject: [PATCH 147/299] reimplement: SHC_3BB0A8C1_0x00539BE0 78.43% jump table order differs --- .../Map/Units/UnitsState/getPeasantGmID.cpp | 91 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 92 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/getPeasantGmID.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/getPeasantGmID.cpp b/src/OpenSHC/Map/Units/UnitsState/getPeasantGmID.cpp new file mode 100644 index 000000000..0bc5980be --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/getPeasantGmID.cpp @@ -0,0 +1,91 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/IO/Graphics/GmID.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::IO::Graphics::GmID; + + // FUNCTION: STRONGHOLDCRUSADER 0x00539BE0 + GmID UnitsState::getPeasantGmID(int unitID) + { + switch (this->units[unitID].unitType) { + case OpenSHC::Map::Units::UT_BURNINGMAN: + return OpenSHC::IO::Graphics::GID_BODY_MAN_BURNING; + case OpenSHC::Map::Units::UT_WOODCUTTER: + return OpenSHC::IO::Graphics::GID_BODY_WOODCUTTER; + case OpenSHC::Map::Units::UT_FLETCHER: + return OpenSHC::IO::Graphics::GID_BODY_FLETCHER; + case OpenSHC::Map::Units::UT_TUNNELER: + return OpenSHC::IO::Graphics::GID_BODY_TUNNELOR; + case OpenSHC::Map::Units::UT_HUNTER: + return OpenSHC::IO::Graphics::GID_BODY_HUNTER; + case OpenSHC::Map::Units::UT_QUARRYOX: + return OpenSHC::IO::Graphics::GID_BODY_OX; + case OpenSHC::Map::Units::UT_PITCHMAN: + return OpenSHC::IO::Graphics::GID_BODY_PITCH_WORKER; + case OpenSHC::Map::Units::UT_WHEATFARMER: + case OpenSHC::Map::Units::UT_HOPSFARMER: + case OpenSHC::Map::Units::UT_APPLEFARMER: + case OpenSHC::Map::Units::UT_DAIRYFARMER: + return OpenSHC::IO::Graphics::GID_BODY_FARMER; + case OpenSHC::Map::Units::UT_MILLER: + return OpenSHC::IO::Graphics::GID_BODY_MILLER; + case OpenSHC::Map::Units::UT_BAKER: + return OpenSHC::IO::Graphics::GID_BODY_BAKER; + case OpenSHC::Map::Units::UT_BREWER: + return OpenSHC::IO::Graphics::GID_BODY_BREWER; + case OpenSHC::Map::Units::UT_POLETURNER: + return OpenSHC::IO::Graphics::GID_BODY_POLETURNER; + case OpenSHC::Map::Units::UT_SMITH: + return OpenSHC::IO::Graphics::GID_BODY_BLACKSMITH; + case OpenSHC::Map::Units::UT_ARMORER: + return OpenSHC::IO::Graphics::GID_BODY_ARMOURER; + case OpenSHC::Map::Units::UT_TANNER: + return OpenSHC::IO::Graphics::GID_BODY_TANNER; + case OpenSHC::Map::Units::UT_MINER: + case OpenSHC::Map::Units::UT_TRANSPORTMINER: + return OpenSHC::IO::Graphics::GID_BODY_IRON_MINER; + case OpenSHC::Map::Units::UT_PRIEST: + return OpenSHC::IO::Graphics::GID_BODY_PRIEST; + case OpenSHC::Map::Units::UT_HEALER: + return OpenSHC::IO::Graphics::GID_BODY_HEALER; + case OpenSHC::Map::Units::UT_DRUNK: + return OpenSHC::IO::Graphics::GID_BODY_DRUNKARD; + case OpenSHC::Map::Units::UT_TRADER: + return OpenSHC::IO::Graphics::GID_BODY_TRADER; + case OpenSHC::Map::Units::UT_TRADERHORSE: + return OpenSHC::IO::Graphics::GID_BODY_HORSE_TRADER; + case OpenSHC::Map::Units::UT_COW: + return OpenSHC::IO::Graphics::GID_BODY_COW; + case OpenSHC::Map::Units::UT_HUNTERDOG: + return OpenSHC::IO::Graphics::GID_BODY_DOG; + case OpenSHC::Map::Units::UT_LORD: + return OpenSHC::IO::Graphics::GID_BODY_LORD; + case OpenSHC::Map::Units::UT_LADY: + return OpenSHC::IO::Graphics::GID_BODY_LADY; + case OpenSHC::Map::Units::UT_JESTER: + return OpenSHC::IO::Graphics::GID_BODY_JESTER; + case OpenSHC::Map::Units::UT_CHICKEN: + return OpenSHC::IO::Graphics::GID_BODY_CHICKEN; + case OpenSHC::Map::Units::UT_MOTHER: + return OpenSHC::IO::Graphics::GID_BODY_MOTHER; + case OpenSHC::Map::Units::UT_CHILD: + return OpenSHC::IO::Graphics::GID_BODY_BOY; + case OpenSHC::Map::Units::UT_JUGGLER: + return OpenSHC::IO::Graphics::GID_BODY_JUGGLER; + case OpenSHC::Map::Units::UT_FIREEATER: + return OpenSHC::IO::Graphics::GID_BODY_FIRE_EATER; + case OpenSHC::Map::Units::UT_BURNING_ANIMAL_BIG: + return OpenSHC::IO::Graphics::GID_BODY_ANIMAL_BURNING_BIG; + case OpenSHC::Map::Units::UT_BURNING_ANIMAL_SMALL: + return OpenSHC::IO::Graphics::GID_BODY_ANIMAL_BURNING_SMALL; + default: + return OpenSHC::IO::Graphics::GID_BODY_PEASANT; + } + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 60b341cc2..c5f45d168 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -59085,7 +59085,7 @@ SHC_3BB0A8C1_0x00539BD5 | 0.0% | Pending SHC_3BB0A8C1_0x00539BD6 | 0.0% | Pending -SHC_3BB0A8C1_0x00539BE0 | 0.0% | Pending +SHC_3BB0A8C1_0x00539BE0 | 78.4% | jump table order differs SHC_3BB0A8C1_0x00539D1C | 0.0% | Pending From b5eb3d72f31f67a030f13a25c55d6b96b838fa63 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:51 +0200 Subject: [PATCH 148/299] reimplement: SHC_3BB0A8C1_0x00540040 49.84% orig caches locals --- ...ctureSetDestinationInDirectionOfTarget.cpp | 82 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 83 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/ifOnADefensiveStructureSetDestinationInDirectionOfTarget.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/ifOnADefensiveStructureSetDestinationInDirectionOfTarget.cpp b/src/OpenSHC/Map/Units/UnitsState/ifOnADefensiveStructureSetDestinationInDirectionOfTarget.cpp new file mode 100644 index 000000000..ef7ec8560 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/ifOnADefensiveStructureSetDestinationInDirectionOfTarget.cpp @@ -0,0 +1,82 @@ +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Map/Units/States/UnitState.hpp" +#include "OpenSHC/Map/Units/UnitInstructionType.hpp" +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_PathFindingState.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Map::Units::UnitInstructionType; + using OpenSHC::Map::Units::States::UnitState; + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x00540040 + BOOLEnum UnitsState::ifOnADefensiveStructureSetDestinationInDirectionOfTarget(int unitID) + { + int _buildingID = DAT_TileMapState::instance.BuildingLayer[this->units[unitID].tile]; + if (_buildingID == 0) { + return FALSE; + } + switch (DAT_BuildingsState::instance.buildings[_buildingID].buildingType) { + 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_WOODGATE1: + 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: + break; + default: + return FALSE; + } + int _targetX; + int _targetY; + if (this->units[unitID].targetingType == OpenSHC::Map::Units::UIT_LIGHT_PITCH) { + _targetX = DAT_TileMapState::instance.pitchDitches[this->units[unitID].targetID_OR_targetBuildingID].x; + _targetY = DAT_TileMapState::instance.pitchDitches[this->units[unitID].targetID_OR_targetBuildingID].y; + } else if (this->units[unitID].targetingType == OpenSHC::Map::Units::UIT_ATTACK_BUILDING) { + _targetX + = (short)DAT_BuildingsState::instance.buildings[this->units[unitID].targetID_OR_targetBuildingID].x; + _targetY + = (short)DAT_BuildingsState::instance.buildings[this->units[unitID].targetID_OR_targetBuildingID].y; + } else if (this->units[unitID].targetingType == OpenSHC::Map::Units::UIT_ATTACK_LAND + || this->units[unitID].shootTargetedUnit == -2) { + _targetX + = (this->units[unitID].shootTargetMicroX + (this->units[unitID].shootTargetMicroX >> 0x1f & 7U)) + >> 3; + _targetY + = (this->units[unitID].shootTargetMicroY + (this->units[unitID].shootTargetMicroY >> 0x1f & 7U)) + >> 3; + } else { + _targetX = this->units[this->units[unitID].shootTargetedUnit].x; + _targetY = this->units[this->units[unitID].shootTargetedUnit].y; + } + int _freeTileX = -1; + int _freeTileY = -1; + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::findClosestFreeTileNearUnitOnBuilding, + DAT_PathFindingState::ptr)(_buildingID, unitID, _targetX, _targetY, &_freeTileX, &_freeTileY); + if (this->units[unitID].x == _freeTileX && this->units[unitID].y == _freeTileY) { + return FALSE; + } + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::setDestinationForUnit, this)( + unitID, _freeTileX, _freeTileY, 0); + this->units[unitID].state.generic + = (OpenSHC::Map::Units::States::US_APPEAR | OpenSHC::Map::Units::States::US_IDLEUnk); + return TRUE; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index c5f45d168..307e7d156 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -60243,7 +60243,7 @@ SHC_3BB0A8C1_0x0053F930 | 0.0% | Pending SHC_3BB0A8C1_0x0053F940 | 0.0% | Pending -SHC_3BB0A8C1_0x00540040 | 0.0% | Pending +SHC_3BB0A8C1_0x00540040 | 49.8% | orig caches locals SHC_3BB0A8C1_0x0054019C | 0.0% | Pending From bb3832992c6686cbaca0c794cb9845b18e270203 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:52 +0200 Subject: [PATCH 149/299] reimplement: SHC_3BB0A8C1_0x00536780 20.48% orig unrolls counter loop x3 --- .../isTowerTileOvercrowdedByCurrentPlayer.cpp | 81 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 82 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/isTowerTileOvercrowdedByCurrentPlayer.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/isTowerTileOvercrowdedByCurrentPlayer.cpp b/src/OpenSHC/Map/Units/UnitsState/isTowerTileOvercrowdedByCurrentPlayer.cpp new file mode 100644 index 000000000..93e6eba71 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/isTowerTileOvercrowdedByCurrentPlayer.cpp @@ -0,0 +1,81 @@ +#include "OpenSHC/Map/TileMapState.func.hpp" +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Map/Buildings/BuildingType.hpp" +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_GameSynchronyState.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Map::Buildings::BuildingType; + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x00536780 + BOOLEnum UnitsState::isTowerTileOvercrowdedByCurrentPlayer(int tile) + { + int _buildingID = DAT_TileMapState::instance.BuildingLayer[tile]; + if (_buildingID == 0) { + return FALSE; + } + switch (DAT_BuildingsState::instance.buildings[_buildingID].buildingType) { + 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: + case OpenSHC::Map::Buildings::BT_STONEKEEP: + case OpenSHC::Map::Buildings::BT_STRONGHOLD: + case OpenSHC::Map::Buildings::BT_KEEPFOUR: + case OpenSHC::Map::Buildings::BT_KEEPFIVE: + break; + default: + return FALSE; + } + int _tileCapacity = DAT_BuildingsState::instance.buildings[_buildingID].widthOrHeight + * DAT_BuildingsState::instance.buildings[_buildingID].widthOrHeight; + if (DAT_BuildingsState::instance.buildings[_buildingID].buildingType + == OpenSHC::Map::Buildings::BT_TOWER1) { + _tileCapacity = 5; + } + int _ownUnitsOnBuilding = 0; + for (int _constructionTile = 0; _constructionTile < DAT_TileMapState::instance.constructionTileCount; + ++_constructionTile) { + MACRO_CALL_MEMBER( + OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, DAT_TileMapState::ptr)( + _constructionTile, DAT_BuildingsState::instance.buildings[_buildingID].widthOrHeight); + for (int _otherUnitID = (short)DAT_TileMapState::instance + .UnitLayer[DAT_ViewportRenderState::instance + .translationMatrix[DAT_TileMapState::instance.buildingY + + (short)DAT_BuildingsState::instance.buildings[_buildingID].y] + .addXgetTile + + DAT_TileMapState::instance.buildingX + + (short)DAT_BuildingsState::instance.buildings[_buildingID].x]; + _otherUnitID != 0; _otherUnitID = (short)this->units[_otherUnitID].nextUnitOnTheSameTile) { + if (this->units[_otherUnitID].owner == DAT_GameSynchronyState::instance.currentPlayerSlotID) { + _ownUnitsOnBuilding = _ownUnitsOnBuilding + 1; + } + } + } + if (_ownUnitsOnBuilding < _tileCapacity / 2) { + return FALSE; + } + if (_tileCapacity <= _ownUnitsOnBuilding) { + return TRUE; + } + int _selectedUnitCount = 0; + for (int i = 0; i < 27; ++i) { + if (i != 6 && i != 8 && i != 11 && i != 12 && i != 13 && i != 14) { + _selectedUnitCount = _selectedUnitCount + (&this->selectionEuropeanArchers)[i]; + } + } + return (BOOLEnum)((_tileCapacity - _ownUnitsOnBuilding) * 2 < _selectedUnitCount); + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 307e7d156..f3376ea96 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -51143,7 +51143,7 @@ SHC_3BB0A8C1_0x00536690 | 92.1% | Style pass, asm differs SHC_3BB0A8C1_0x00536710 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x00536780 | 0.0% | Pending +SHC_3BB0A8C1_0x00536780 | 20.5% | orig unrolls counter loop x3 SHC_3BB0A8C1_0x00536860 | 0.0% | Pending From 8ca1e9913d6ed0381b1a4e1909913266358c927c Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:52 +0200 Subject: [PATCH 150/299] reimplement: SHC_3BB0A8C1_0x00533D50 37.57% branch shape differs --- ...ateUnitFadeAndVisibilityNearStructures.cpp | 112 ++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 113 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/updateUnitFadeAndVisibilityNearStructures.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/updateUnitFadeAndVisibilityNearStructures.cpp b/src/OpenSHC/Map/Units/UnitsState/updateUnitFadeAndVisibilityNearStructures.cpp new file mode 100644 index 000000000..578fa8990 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/updateUnitFadeAndVisibilityNearStructures.cpp @@ -0,0 +1,112 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +#include "OpenSHC/Globals/DAT_BuildingDefinedData.hpp" +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x00533D50 + void UnitsState::updateUnitFadeAndVisibilityNearStructures(int unitID) + { + int _tile = this->units[unitID].tile; + uint _logicFlags = DAT_TileMapState::instance.LogicLayer[_tile]; + byte _gateFadeType = 0; + byte _towerFadeType = 0; + byte _fadeType = 0; + bool _isOnDefensiveStructure = false; + if (this->units[unitID].unknownCountdown_0x402 != 0) { + this->units[unitID].unknownCountdown_0x402 = this->units[unitID].unknownCountdown_0x402 - 1; + } + if (DAT_TileMapState::instance.BuildingLayer[_tile] == 0) { + if ((_logicFlags & 0x100) != 0) { + _isOnDefensiveStructure = true; + } + } else { + switch (DAT_BuildingsState::instance.buildings[DAT_TileMapState::instance.BuildingLayer[_tile]] + .buildingType) { + case OpenSHC::Map::Buildings::BT_GATEHOUSELARGE: + case OpenSHC::Map::Buildings::BT_GATEHOUSESMALL: + _gateFadeType = 0xb; + break; + case OpenSHC::Map::Buildings::BT_WOODGATE1: + _gateFadeType = 10; + break; + case OpenSHC::Map::Buildings::BT_TOWER1: + _towerFadeType = 1; + break; + case OpenSHC::Map::Buildings::BT_TOWER2: + _towerFadeType = 2; + break; + case OpenSHC::Map::Buildings::BT_TOWER3: + _towerFadeType = 3; + break; + case OpenSHC::Map::Buildings::BT_TOWER4: + case OpenSHC::Map::Buildings::BT_TOWER5: + _towerFadeType = 4; + } + } + if (this->units[unitID].field171_0x308 == 2 && _isOnDefensiveStructure) { + _fadeType = 1; + } + if (this->units[unitID].field171_0x308 == 1 && _towerFadeType != 0) { + _fadeType = _towerFadeType; + } + if (this->units[unitID].field171_0x308 == 0 && _gateFadeType != 0) { + if ((DAT_TileMapState::instance.LogicLayer[this->units[unitID].destinationTilePosition] & 0x100U) != 0 + || DAT_BuildingDefinedData::instance.IsGateOrTowerArray[(short)DAT_BuildingsState::instance + .buildings[DAT_TileMapState::instance + .BuildingLayer[this->units[unitID].destinationTilePosition]] + .buildingType] + != FALSE) { + _fadeType = _gateFadeType; + } + } + if (_gateFadeType != 0) { + if ((DAT_TileMapState::instance.LogicLayer[this->units[unitID].destinationTilePosition] & 0x100U) == 0 + || (DAT_TileMapState::instance.LogicLayer[this->units[unitID].destinationTilePosition] & 2U) != 0) { + this->units[unitID].unknownCountdown_0x402 + = (DAT_BuildingDefinedData::instance.IsGateOrTowerArray[(short)DAT_BuildingsState::instance + .buildings[DAT_TileMapState::instance + .BuildingLayer[this->units[unitID].destinationTilePosition]] + .buildingType] + != FALSE) + - 1U + & 10; + } else { + this->units[unitID].unknownCountdown_0x402 = 0; + } + } + if (_isOnDefensiveStructure) { + this->units[unitID].field171_0x308 = 1; + } else if (_towerFadeType == 0) { + this->units[unitID].field171_0x308 = -(ushort)(_gateFadeType != 0) & 3; + } else { + this->units[unitID].field171_0x308 = 2; + } + if (this->units[unitID].unknownCountdown_0x402 == 0 + || (DAT_TileMapState::instance.MiscDisplayLayer[this->units[unitID].nextTileUnk] & 0x10) != 0) { + this->units[unitID].vanish = 0; + } else if ((DAT_TileMapState::instance.MiscDisplayLayer[this->units[unitID].currentTilePosition_2Unk] + & 0x10) + == 0) { + if (this->units[unitID].vanish < 1) { + this->units[unitID].vanish = 1; + } + } else { + this->units[unitID].vanish = 0xf; + } + if (_fadeType != 0) { + this->units[unitID].fadeType = _fadeType; + this->units[unitID].fadeCounter = 0; + } + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index f3376ea96..997d9b295 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -50693,7 +50693,7 @@ SHC_3BB0A8C1_0x00533C70 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00533CA0 | 90.9% | loop exit shape differs -SHC_3BB0A8C1_0x00533D50 | 0.0% | Pending +SHC_3BB0A8C1_0x00533D50 | 37.6% | branch shape differs SHC_3BB0A8C1_0x00533F48 | 0.0% | Pending From fa515e58cdbaa082427e59b8fc82fbef5b9f0d64 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:53 +0200 Subject: [PATCH 151/299] reimplement: SHC_3BB0A8C1_0x0052F260 19.32% loop shape differs --- .../setMoveDelayForUnitsOnSameTiles.cpp | 93 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/setMoveDelayForUnitsOnSameTiles.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/setMoveDelayForUnitsOnSameTiles.cpp b/src/OpenSHC/Map/Units/UnitsState/setMoveDelayForUnitsOnSameTiles.cpp new file mode 100644 index 000000000..3b0457478 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/setMoveDelayForUnitsOnSameTiles.cpp @@ -0,0 +1,93 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" + +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/MSVC_SecurityCookie.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + // FUNCTION: STRONGHOLDCRUSADER 0x0052F260 + void UnitsState::setMoveDelayForUnitsOnSameTiles(int unitID, int unitIDCurrentTilePosition) + { + ushort _unitIDArray[2010]; + int _lowestMovementSpeed = 0x14; + this->units[unitID].unitOrderWhenOnSameTile = 0; + if (this->units[unitID].unknownTestAgainst0_2 != 0) { + return; + } + this->units[unitID].field40_0x5a = 0; + /* if current tile position is not occupied */ + if (DAT_TileMapState::instance.UnitLayer[unitIDCurrentTilePosition] == 0) { + DAT_TileMapState::instance.UnitLayer[unitIDCurrentTilePosition] = (ushort)unitID; + this->units[unitID].nextUnitOnTheSameTile = 0; + return; + } + /* if current tile position is occupied */ + bool _isInserted = false; + int _unitIDOfAUnitOnSameTile = (short)DAT_TileMapState::instance.UnitLayer[unitIDCurrentTilePosition]; + int _index = 0; + int _writeIndex = 0; + while (true) { + _writeIndex = _index; + if (unitID < _unitIDOfAUnitOnSameTile && !_isInserted) { + _unitIDArray[_index] = (ushort)unitID; + _writeIndex = _index + 1; + _isInserted = true; + } + _unitIDArray[_writeIndex] = (ushort)_unitIDOfAUnitOnSameTile; + _unitIDOfAUnitOnSameTile = (short)this->units[_unitIDOfAUnitOnSameTile].nextUnitOnTheSameTile; + if (_unitIDOfAUnitOnSameTile < 1) { + break; + } + _index = _writeIndex + 1; + _writeIndex = _index; + if (_index >= 2000) { + break; + } + } + _writeIndex = _writeIndex + 1; + if (!_isInserted) { + _unitIDArray[_writeIndex] = (ushort)unitID; + _writeIndex = _writeIndex + 2; + } + _unitIDArray[_writeIndex] = 0; + DAT_TileMapState::instance.UnitLayer[unitIDCurrentTilePosition] = _unitIDArray[0]; + this->units[(short)_unitIDArray[0]].unitOrderWhenOnSameTile = 0; + int _previousUnitID = (short)_unitIDArray[0]; + for (int _order = 1; _order < 2001; ++_order) { + this->units[_previousUnitID].nextUnitOnTheSameTile = _unitIDArray[_order]; + if ((short)_unitIDArray[_order] < 1) { + break; + } + this->units[(short)_unitIDArray[_order]].unitOrderWhenOnSameTile = (short)_order; + _previousUnitID = (short)_unitIDArray[_order]; + } + for (int i = 0; i < 2000; ++i) { + if ((short)_unitIDArray[i] < 1) { + break; + } + if (this->units[(short)_unitIDArray[i]].tunnelerFinishedDigging == 2 + && this->units[(short)_unitIDArray[i]].movementSpeed < _lowestMovementSpeed) { + _lowestMovementSpeed = this->units[(short)_unitIDArray[i]].movementSpeed; + } + } + for (int i = 0; i < 2000; ++i) { + if ((short)_unitIDArray[i] < 1) { + break; + } + if (this->units[(short)_unitIDArray[i]].tunnelerFinishedDigging == 2 + && this->units[(short)_unitIDArray[i]].moveDelay == 0) { + if (_lowestMovementSpeed < this->units[(short)_unitIDArray[i]].movementSpeed) { + this->units[(short)_unitIDArray[i]].moveDelay + = this->units[(short)_unitIDArray[i]].unitOrderWhenOnSameTile / 2 + 1; + } else { + _lowestMovementSpeed = 0; + } + } + } + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 997d9b295..546d031ae 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -49323,7 +49323,7 @@ SHC_3BB0A8C1_0x0052F0A0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0052F0D0 | 41.0% | branch shape differs -SHC_3BB0A8C1_0x0052F260 | 0.0% | Pending +SHC_3BB0A8C1_0x0052F260 | 19.3% | loop shape differs SHC_3BB0A8C1_0x0052F440 | 66.7% | loop shape differs From 9ece5e4169a65dd75cf9e4f5d2c0bee6e32caa1e Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:53 +0200 Subject: [PATCH 152/299] reimplement: SHC_3BB0A8C1_0x00531000 38.28% orig caches unitTypes local --- .../UnitsState/shouldUnitsEngageInMelee.cpp | 123 ++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 124 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/shouldUnitsEngageInMelee.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/shouldUnitsEngageInMelee.cpp b/src/OpenSHC/Map/Units/UnitsState/shouldUnitsEngageInMelee.cpp new file mode 100644 index 000000000..9e891e0b6 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/shouldUnitsEngageInMelee.cpp @@ -0,0 +1,123 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Game/GameMode.hpp" +#include "OpenSHC/Map/Units/UnitType.hpp" +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +#include "OpenSHC/Globals/DAT_GameState.hpp" +#include "OpenSHC/Globals/DAT_GameSynchronyState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Game::GameMode; + using OpenSHC::Map::Units::UnitType; + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x00531000 + BOOLEnum UnitsState::shouldUnitsEngageInMelee(int unitID_1, int unitID_2) + { + if (this->units[unitID_1].unitType == OpenSHC::Map::Units::UT_TRADER + || this->units[unitID_1].unitType == OpenSHC::Map::Units::UT_TRADERHORSE) { + return TRUE; + } + if (this->units[unitID_2].unitType == OpenSHC::Map::Units::UT_TRADER + || this->units[unitID_2].unitType == OpenSHC::Map::Units::UT_TRADERHORSE + || this->units[unitID_1].unitType == OpenSHC::Map::Units::UT_GHOST + || this->units[unitID_2].unitType == OpenSHC::Map::Units::UT_GHOST) { + return TRUE; + } + if (this->units[unitID_1].unitType == OpenSHC::Map::Units::UT_CAMELSHBEAR) { + if (this->units[unitID_2].unitType == OpenSHC::Map::Units::UT_WOODCUTTER) { + return FALSE; + } + if (this->units[unitID_2].unitType == OpenSHC::Map::Units::UT_LIONSHWOLF) { + return FALSE; + } + return TRUE; + } + if (this->units[unitID_2].unitType == OpenSHC::Map::Units::UT_CAMELSHBEAR) { + if (this->units[unitID_1].unitType == OpenSHC::Map::Units::UT_WOODCUTTER + || this->units[unitID_1].unitType == OpenSHC::Map::Units::UT_LIONSHWOLF) { + return FALSE; + } + return TRUE; + } + if (this->units[unitID_1].isStalked == 0) { + if (this->units[unitID_2].isStalked != 0) { + if (this->units[unitID_2].unitType == OpenSHC::Map::Units::UT_LIONSHWOLF) { + return FALSE; + } + if (this->units[unitID_2].unitType == OpenSHC::Map::Units::UT_CAGEDOG) { + return (BOOLEnum)(DAT_GameState::instance.mapAndTime + .playerTeams[this->units[unitID_2].displayColorPlayerID] + == DAT_GameState::instance.mapAndTime.playerTeams[this->units[unitID_1].owner]); + } + if (this->units[unitID_2].unitType == OpenSHC::Map::Units::UT_RABBIT + || this->units[unitID_2].unitType == OpenSHC::Map::Units::UT_QUARRYOX + || this->units[unitID_2].unitType == OpenSHC::Map::Units::UT_COW) { + return FALSE; + } + return (BOOLEnum)(this->units[unitID_2].unitType != OpenSHC::Map::Units::UT_HUNTERDOG); + } + if (DAT_GameState::instance.mapAndTime.skirmishNoRushTicks == 0 + || DAT_GameSynchronyState::instance.currentGameMode == OpenSHC::Game::GM_SKIRMISH_SINGLE_PLAYER + || DAT_GameSynchronyState::instance.currentGameMode == OpenSHC::Game::GM_SOLITARY) { + return FALSE; + } + return TRUE; + } + if (this->units[unitID_1].unitType == OpenSHC::Map::Units::UT_LIONSHWOLF) { + if (this->units[unitID_2].unitType == OpenSHC::Map::Units::UT_ANTELOPESHDEER) { + return FALSE; + } + if (this->units[unitID_2].unitType == OpenSHC::Map::Units::UT_COW) { + return FALSE; + } + if (this->units[unitID_2].unitType == OpenSHC::Map::Units::UT_RABBIT) { + return FALSE; + } + if (this->units[unitID_2].unitType == OpenSHC::Map::Units::UT_HUNTERDOG) { + return FALSE; + } + } else if (this->units[unitID_1].unitType == OpenSHC::Map::Units::UT_CAGEDOG) { + if (this->units[unitID_2].unitType == OpenSHC::Map::Units::UT_ANTELOPESHDEER) { + return FALSE; + } + if (this->units[unitID_2].unitType == OpenSHC::Map::Units::UT_COW) { + return FALSE; + } + if (this->units[unitID_2].unitType == OpenSHC::Map::Units::UT_RABBIT) { + return FALSE; + } + if (this->units[unitID_2].unitType == OpenSHC::Map::Units::UT_HUNTERDOG) { + return FALSE; + } + if (this->units[unitID_2].isStalked != 0) { + return TRUE; + } + return ( + BOOLEnum)(DAT_GameState::instance.mapAndTime.playerTeams[this->units[unitID_1].displayColorPlayerID] + == DAT_GameState::instance.mapAndTime.playerTeams[this->units[unitID_2].owner]); + } else if (this->units[unitID_1].unitType != OpenSHC::Map::Units::UT_HUNTERDOG) { + return TRUE; + } else { + if (this->units[unitID_2].unitType == OpenSHC::Map::Units::UT_RABBIT) { + return FALSE; + } + if (this->units[unitID_2].unitType == OpenSHC::Map::Units::UT_LIONSHWOLF) { + return FALSE; + } + if (this->units[unitID_2].unitType == OpenSHC::Map::Units::UT_CAGEDOG) { + return FALSE; + } + } + if (this->units[unitID_2].isStalked == 0) { + return FALSE; + } + return TRUE; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 546d031ae..e2bb074b5 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -49661,7 +49661,7 @@ SHC_3BB0A8C1_0x00530F20 | 0.0% | Pending SHC_3BB0A8C1_0x00530FD0 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x00531000 | 0.0% | Pending +SHC_3BB0A8C1_0x00531000 | 38.3% | orig caches unitTypes local SHC_3BB0A8C1_0x005311F0 | 100.0% | Reimplemented From d914f1fb3b122c9fa6ed2865d17c458b05bdb5c0 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:53 +0200 Subject: [PATCH 153/299] reimplement: SHC_3BB0A8C1_0x00533630 20.60% orig walks enemy array ptr --- ...ndAttackNearbyEnemyLaddermanInPosition.cpp | 84 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 85 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/findAndAttackNearbyEnemyLaddermanInPosition.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/findAndAttackNearbyEnemyLaddermanInPosition.cpp b/src/OpenSHC/Map/Units/UnitsState/findAndAttackNearbyEnemyLaddermanInPosition.cpp new file mode 100644 index 000000000..226778808 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/findAndAttackNearbyEnemyLaddermanInPosition.cpp @@ -0,0 +1,84 @@ +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Map/LogicHelpers/Logic1.hpp" +#include "OpenSHC/Map/Units/States/UnitState.hpp" +#include "OpenSHC/Map/Units/UnitType.hpp" +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +#include "OpenSHC/Globals/DAT_GameState.hpp" +#include "OpenSHC/Globals/DAT_PathFindingState.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Map::Units::UnitType; + using OpenSHC::Map::Units::States::UnitState; + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x00533630 + BOOLEnum UnitsState::findAndAttackNearbyEnemyLaddermanInPosition(int unitID) + { + if ((DAT_TileMapState::instance.LogicLayer[this->units[unitID].tile] & LogicHelpers::L_WALL_OR_GATEHOUSE) == 0) { + return FALSE; + } + short _owner = this->units[unitID].owner; + ushort _areaOfUnit = DAT_TileMapState::instance.PathConnectionLayer[this->units[unitID].tile]; + int _bestEnemyUnitID = 0; + int _minDistance = 1000; + for (int i = 0; i < DAT_GameState::instance.playerDataArray[_owner].enemies; ++i) { + int _enemyUnitID = DAT_GameState::instance.playerDataArray[_owner].enemyIDArray[i]; + if (this->units[_enemyUnitID].unitType != OpenSHC::Map::Units::UT_E_LADDER) { + continue; + } + if (this->units[_enemyUnitID].state.generic != (UnitState)3) { + continue; + } + if (MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::isUsableClimbWithinArea, + DAT_PathFindingState::ptr)((short)_areaOfUnit, this->units[_enemyUnitID].wallDataID) + == FALSE) { + continue; + } + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::findPositionForGivenClimbArea, + DAT_PathFindingState::ptr)( + (short)_areaOfUnit, this->units[_enemyUnitID].x, this->units[_enemyUnitID].y); + int _distanceX; + if (DAT_PathFindingState::instance.climbX < this->units[unitID].x) { + _distanceX = this->units[unitID].x - DAT_PathFindingState::instance.climbX; + } else { + _distanceX = DAT_PathFindingState::instance.climbX - this->units[unitID].x; + } + int _distanceY; + if (DAT_PathFindingState::instance.climbY < this->units[unitID].y) { + _distanceY = this->units[unitID].y - DAT_PathFindingState::instance.climbY; + } else { + _distanceY = DAT_PathFindingState::instance.climbY - this->units[unitID].y; + } + if (_distanceX < _distanceY) { + /* stores the largest distance into _distanceX */ + _distanceX = _distanceY; + } + if (this->units[_enemyUnitID].targetShootRelated != 0) { + _distanceX = _distanceX + 10; + } + if (_distanceX < _minDistance) { + this->climbX2 = DAT_PathFindingState::instance.climbX; + this->climbY2 = DAT_PathFindingState::instance.climbY; + _bestEnemyUnitID = _enemyUnitID; + _minDistance = _distanceX; + } + } + if (_bestEnemyUnitID == 0) { + return FALSE; + } + this->units[unitID].shootTargetedUnit = (short)_bestEnemyUnitID; + this->units[unitID].targetUID = this->units[_bestEnemyUnitID].uid; + this->units[unitID].distanceToEnemyUnitLadders = (short)_minDistance; + this->units[_bestEnemyUnitID].targetShootRelated = 0x19; + return TRUE; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index e2bb074b5..215065239 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -50673,7 +50673,7 @@ SHC_3BB0A8C1_0x005334A0 | 41.2% | orig caches unitType local SHC_3BB0A8C1_0x00533580 | 24.5% | orig caches locals -SHC_3BB0A8C1_0x00533630 | 0.0% | Pending +SHC_3BB0A8C1_0x00533630 | 20.6% | orig walks enemy array ptr SHC_3BB0A8C1_0x00533810 | 80.3% | orig walks matrix row ptr From cc8f8f00096b73d0331ac1a043490c722bc6b7e1 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:54 +0200 Subject: [PATCH 154/299] reimplement: SHC_3BB0A8C1_0x0054BFC0 46.09% branch shape differs --- .../Map/Units/UnitsState/updateClimbing.cpp | 88 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 89 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/updateClimbing.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/updateClimbing.cpp b/src/OpenSHC/Map/Units/UnitsState/updateClimbing.cpp new file mode 100644 index 000000000..4d3c355ad --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/updateClimbing.cpp @@ -0,0 +1,88 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Map/Units/States/UnitState.hpp" +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +#include "OpenSHC/Globals/DAT_PathFindingState.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Map::Units::States::UnitState; + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x0054BFC0 + BOOLEnum UnitsState::updateClimbing(int unitID) + { + int _climbDataID = this->units[unitID].climbDataID; + if (_climbDataID == 0) { + return TRUE; + } + if (_climbDataID == 200) { + return FALSE; + } + if (DAT_PathFindingState::instance.climbData[_climbDataID].climbDataRelated + != this->units[unitID].climbDataRelated) { + this->units[unitID].climbDataID = 0; + return FALSE; + } + *(undefined2*)&this->units[unitID].climbingState = 0xffff; + if (DAT_PathFindingState::instance.climbData[_climbDataID].type == 1) { + int _ladderUnitID + = (short)DAT_TileMapState::instance + .UnitLayer[DAT_PathFindingState::instance.climbData[_climbDataID].bottomTilePosition]; + if (_ladderUnitID == 0) { + return FALSE; + } + while (DAT_PathFindingState::instance.climbData[_climbDataID].unitID != _ladderUnitID) { + _ladderUnitID = (short)this->units[_ladderUnitID].nextUnitOnTheSameTile; + if (_ladderUnitID == 0) { + return FALSE; + } + } + short _climbDirection = this->units[unitID].climbDirection; + this->units[unitID].facingDirection = this->units[_ladderUnitID].facingDirection; + this->units[unitID].usingTeleport = (short)DAT_PathFindingState::instance.climbData[_climbDataID].type; + this->units[unitID].field203_0x35c = 0; + *(undefined2*)&this->units[unitID].climbingState = 0; + if (_climbDirection == 0) { + this->units[unitID].climbingDirection = 0; + } else { + this->units[unitID].climbingDirection = 1; + } + if (this->units[unitID].climbingDirection == 1) { + this->units[unitID].terrainOrClimbHeight = this->units[unitID].terrainOrClimbHeight - 40; + } + this->units[unitID].unknownStateCopyClimbRelated = this->units[unitID].state.generic; + this->units[unitID].state.generic = (UnitState)0x68; + this->units[unitID].animationCycleNumber = 0; + } else if (DAT_PathFindingState::instance.climbData[_climbDataID].type == 7 + || DAT_PathFindingState::instance.climbData[_climbDataID].type == 6 + || DAT_PathFindingState::instance.climbData[_climbDataID].type == 5 + || DAT_PathFindingState::instance.climbData[_climbDataID].type == 4 + || DAT_PathFindingState::instance.climbData[_climbDataID].type == 3) { + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::exitLadder, this)(unitID); + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::setDestinationForUnit, this)( + unitID, this->units[unitID].destinationX_2Unk, this->units[unitID].destinationY_2Unk, 0); + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::changeDestinationByLeftover, this)(unitID); + } + if (this->units[unitID].climbDirection != 0) { + /* Climb down */ + this->units[unitID].mimicCurrentXPosition + = (short)DAT_PathFindingState::instance.climbData[_climbDataID].bottomXPosition; + this->units[unitID].mimicCurrentYPosition + = (short)DAT_PathFindingState::instance.climbData[_climbDataID].bottomYPosition; + return TRUE; + } + /* Climb up */ + this->units[unitID].mimicCurrentXPosition + = (short)DAT_PathFindingState::instance.climbData[_climbDataID].topXPosition; + this->units[unitID].mimicCurrentYPosition + = (short)DAT_PathFindingState::instance.climbData[_climbDataID].topYPosition; + return TRUE; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 215065239..f0717b32e 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -62501,7 +62501,7 @@ SHC_3BB0A8C1_0x0054BFB2 | 0.0% | Pending SHC_3BB0A8C1_0x0054BFB3 | 0.0% | Pending -SHC_3BB0A8C1_0x0054BFC0 | 0.0% | Pending +SHC_3BB0A8C1_0x0054BFC0 | 46.1% | branch shape differs SHC_3BB0A8C1_0x0054C1C0 | 0.0% | Pending From c86a5812b1c8f19bf5f824df409683b688f584c5 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:54 +0200 Subject: [PATCH 155/299] reimplement: SHC_3BB0A8C1_0x00534EE0 88.14% reg alloc differs --- .../selectFirstUnitInDragBoxAnyPlayer.cpp | 114 ++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 115 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/selectFirstUnitInDragBoxAnyPlayer.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/selectFirstUnitInDragBoxAnyPlayer.cpp b/src/OpenSHC/Map/Units/UnitsState/selectFirstUnitInDragBoxAnyPlayer.cpp new file mode 100644 index 000000000..68dd23ee2 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/selectFirstUnitInDragBoxAnyPlayer.cpp @@ -0,0 +1,114 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Map/Units/States/UnitState.hpp" +#include "OpenSHC/Map/Units/UnitLogicState.hpp" +#include "OpenSHC/Map/Units/UnitType.hpp" + +#include "OpenSHC/Globals/DAT_CurrentUnitSlotID.hpp" +#include "OpenSHC/Globals/DAT_GameSynchronyState.hpp" +#include "OpenSHC/Globals/DAT_MouseState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Map::Units::UnitLogicState; + using OpenSHC::Map::Units::UnitType; + using OpenSHC::Map::Units::States::UnitState; + + // FUNCTION: STRONGHOLDCRUSADER 0x00534EE0 + void UnitsState::selectFirstUnitInDragBoxAnyPlayer() + { + LONG _boxLeft; + LONG _boxRight; + if (DAT_MouseState::instance.selectionBox.right < DAT_MouseState::instance.selectionBox.left) { + _boxLeft = DAT_MouseState::instance.selectionBox.right; + _boxRight = DAT_MouseState::instance.selectionBox.left; + } else { + _boxLeft = DAT_MouseState::instance.selectionBox.left; + _boxRight = DAT_MouseState::instance.selectionBox.right; + } + LONG _boxTop; + LONG _boxBottom; + if (DAT_MouseState::instance.selectionBox.bottom < DAT_MouseState::instance.selectionBox.top) { + _boxTop = DAT_MouseState::instance.selectionBox.bottom; + _boxBottom = DAT_MouseState::instance.selectionBox.top; + } else { + _boxTop = DAT_MouseState::instance.selectionBox.top; + _boxBottom = DAT_MouseState::instance.selectionBox.bottom; + } + this->field14_0x55c = 0; + this->totalUnitsInSelection = 0; + for (DAT_CurrentUnitSlotID::instance = 1; (int)DAT_CurrentUnitSlotID::instance < (int)this->maxUnitCount; + DAT_CurrentUnitSlotID::instance = DAT_CurrentUnitSlotID::instance + 1) { + this->units[DAT_CurrentUnitSlotID::instance].isSelected = 0; + if (this->units[DAT_CurrentUnitSlotID::instance].logicalState != OpenSHC::Map::Units::ULS_NORMAL) { + continue; + } + if (this->units[DAT_CurrentUnitSlotID::instance].dying != 0) { + continue; + } + if (this->units[DAT_CurrentUnitSlotID::instance].unknownTestAgainst0_2 != 0) { + continue; + } + if (this->units[DAT_CurrentUnitSlotID::instance].state.generic + == OpenSHC::Map::Units::States::US_JESTER_ROAM_TO) { + continue; + } + if (this->units[DAT_CurrentUnitSlotID::instance].isSelectable_OR_matchTime == 0) { + continue; + } + if (this->units[DAT_CurrentUnitSlotID::instance].unitType == OpenSHC::Map::Units::UT_S_TOWER + && this->units[DAT_CurrentUnitSlotID::instance].state.generic + == (OpenSHC::Map::Units::States::US_STAND_UPUnk | OpenSHC::Map::Units::States::US_IDLEUnk)) { + continue; + } + if (this->units[DAT_CurrentUnitSlotID::instance].unitType == OpenSHC::Map::Units::UT_TUNNELER + && (this->units[DAT_CurrentUnitSlotID::instance].state.generic + == OpenSHC::Map::Units::States::US_LOOK_AROUNDUnk + || this->units[DAT_CurrentUnitSlotID::instance].state.generic + == OpenSHC::Map::Units::States::US_STAND_UPUnk)) { + continue; + } + if (this->units[DAT_CurrentUnitSlotID::instance].drawX == 0 + && this->units[DAT_CurrentUnitSlotID::instance].drawY == 0) { + continue; + } + if (this->units[DAT_CurrentUnitSlotID::instance].drawX + + this->units[DAT_CurrentUnitSlotID::instance].drawXOffset + >= _boxRight) { + continue; + } + if (this->units[DAT_CurrentUnitSlotID::instance].drawY + + this->units[DAT_CurrentUnitSlotID::instance].someDrawYOffset + >= _boxBottom) { + continue; + } + if (this->units[DAT_CurrentUnitSlotID::instance].spriteWidthUnk + + this->units[DAT_CurrentUnitSlotID::instance].drawX + + this->units[DAT_CurrentUnitSlotID::instance].drawXOffset + < _boxLeft) { + continue; + } + if (this->units[DAT_CurrentUnitSlotID::instance].spriteHeightUnk + + this->units[DAT_CurrentUnitSlotID::instance].drawY + + this->units[DAT_CurrentUnitSlotID::instance].someDrawYOffset + < _boxTop) { + continue; + } + this->units[DAT_CurrentUnitSlotID::instance].isSelected = 1; + this->totalUnitsInSelection = this->totalUnitsInSelection + 1; + if (this->units[DAT_CurrentUnitSlotID::instance].owner + == DAT_GameSynchronyState::instance.currentPlayerSlotID) { + return; + } + if (this->units[DAT_CurrentUnitSlotID::instance].owner == 0) { + return; + } + this->field14_0x55c = this->units[DAT_CurrentUnitSlotID::instance].owner; + return; + } + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index f0717b32e..bb4432a28 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -50849,7 +50849,7 @@ SHC_3BB0A8C1_0x00534D10 | 0.0% | Pending SHC_3BB0A8C1_0x00534D80 | 0.0% | Pending -SHC_3BB0A8C1_0x00534EE0 | 0.0% | Pending +SHC_3BB0A8C1_0x00534EE0 | 88.1% | reg alloc differs SHC_3BB0A8C1_0x00534F50 | 0.0% | Pending From 9aba17698c0e6e91b0e15cd8644dca6bad4b40ca Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:54 +0200 Subject: [PATCH 156/299] reimplement: SHC_3BB0A8C1_0x00535E20 40.00% branch shape differs --- .../selectSiegeEngineAndPlayFeedback.cpp | 81 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 82 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/selectSiegeEngineAndPlayFeedback.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/selectSiegeEngineAndPlayFeedback.cpp b/src/OpenSHC/Map/Units/UnitsState/selectSiegeEngineAndPlayFeedback.cpp new file mode 100644 index 000000000..0b3ca49b6 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/selectSiegeEngineAndPlayFeedback.cpp @@ -0,0 +1,81 @@ +#include "OpenSHC/Audio/SFX/SFXState.func.hpp" +#include "OpenSHC/Map/Units/TribesState.func.hpp" +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Audio/SFX/SpeechEffectID.hpp" +#include "OpenSHC/Map/Units/UnitType.hpp" +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +#include "OpenSHC/Globals/DAT_GameSynchronyState.hpp" +#include "OpenSHC/Globals/DAT_SFXState.hpp" +#include "OpenSHC/Globals/DAT_TribesState.hpp" +#include "OpenSHC/Globals/DAT_UIDragDropDefinedData.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Audio::SFX::SpeechEffectID; + using OpenSHC::Map::Units::UnitType; + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x00535E20 + void UnitsState::selectSiegeEngineAndPlayFeedback(int playerID, int unitID, int tribeID) + { + MACRO_CALL_MEMBER(OpenSHC::Map::Units::TribesState_Func::removeUnitFromTribe, DAT_TribesState::ptr)( + unitID, this->units[unitID].tribeID); + this->units[unitID].isSelected = 1; + this->units[unitID].selectionRelatedFlag = 1; + this->units[unitID].ifSelectedThenPlayerID = (short)playerID; + this->unitCountOfSelection[playerID] = this->unitCountOfSelection[playerID] + 1; + MACRO_CALL_MEMBER(OpenSHC::Map::Units::TribesState_Func::addUnitToTribeAndUpdateTribeMovementSpeed, + DAT_TribesState::ptr)(playerID, unitID, tribeID); + if (DAT_TribesState::instance.tribes[tribeID].owner + != DAT_GameSynchronyState::instance.currentPlayerSlotID) { + DAT_UIDragDropDefinedData::instance.MenuView_TriggerInitial = TRUE; + return; + } + UnitType _unitType = (UnitType)(short)this->units[unitID].unitType; + if (_unitType == OpenSHC::Map::Units::UT_S_CATAPULT || _unitType == OpenSHC::Map::Units::UT_S_TOWER + || _unitType == OpenSHC::Map::Units::UT_S_BATTERINGRAM || _unitType == OpenSHC::Map::Units::UT_S_SHIELD + || _unitType == OpenSHC::Map::Units::UT_S_BALLISTA || _unitType == OpenSHC::Map::Units::UT_S_FBALLISTA + || _unitType == OpenSHC::Map::Units::UT_S_TREBUCHET + || _unitType == OpenSHC::Map::Units::UT_S_MANGONEL) { + int _siegeEngineUnitID = DAT_TribesState::instance.tribes[tribeID].selectionTargetUnitID; + int _remainingEngineers = MACRO_CALL_MEMBER( + OpenSHC::Map::Units::UnitsState_Func::getRemainingRequiredEngineers, this)(_siegeEngineUnitID); + if (_remainingEngineers > 0) { + if (this->units[_siegeEngineUnitID] + .digTileX__OR__countCurrentlyManningEnginers__OR__forCowsRandomBelow300 + == 0 + || _remainingEngineers > 3) { + MACRO_CALL_MEMBER(OpenSHC::Audio::SFX::SFXState_Func::playUnitSpeechEffect, DAT_SFXState::ptr)( + 0xe); + } else if (_remainingEngineers == 1) { + MACRO_CALL_MEMBER(OpenSHC::Audio::SFX::SFXState_Func::playUnitSpeechEffect, DAT_SFXState::ptr)( + 0xb); + } else if (_remainingEngineers == 2) { + MACRO_CALL_MEMBER(OpenSHC::Audio::SFX::SFXState_Func::playUnitSpeechEffect, DAT_SFXState::ptr)( + 0xc); + } else if (_remainingEngineers == 3) { + MACRO_CALL_MEMBER(OpenSHC::Audio::SFX::SFXState_Func::playUnitSpeechEffect, DAT_SFXState::ptr)( + 0xd); + } + DAT_UIDragDropDefinedData::instance.MenuView_TriggerInitial = TRUE; + return; + } + if ((_unitType == OpenSHC::Map::Units::UT_S_CATAPULT + || _unitType == OpenSHC::Map::Units::UT_S_TREBUCHET) + && this->units[_siegeEngineUnitID].stoneAmmunition < 1) { + MACRO_CALL_MEMBER(OpenSHC::Audio::SFX::SFXState_Func::playSpeechSFX, DAT_SFXState::ptr)( + OpenSHC::Audio::SFX::SEID_RESOURCE_NEED25); + DAT_UIDragDropDefinedData::instance.MenuView_TriggerInitial = TRUE; + return; + } + } + MACRO_CALL_MEMBER(OpenSHC::Audio::SFX::SFXState_Func::playUnitSpeech, DAT_SFXState::ptr)(_unitType, 0); + DAT_UIDragDropDefinedData::instance.MenuView_TriggerInitial = TRUE; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index bb4432a28..5b53d59bb 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -51105,7 +51105,7 @@ SHC_3BB0A8C1_0x00535BC0 | 0.0% | Pending SHC_3BB0A8C1_0x00535DF0 | 46.1% | call+reg alloc differs -SHC_3BB0A8C1_0x00535E20 | 0.0% | Pending +SHC_3BB0A8C1_0x00535E20 | 40.0% | branch shape differs SHC_3BB0A8C1_0x00535FD0 | 88.9% | orig walks hotkey ptr From 5e1a76f0eaba039211af5f1ba3e21eee31de688d Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:55 +0200 Subject: [PATCH 157/299] reimplement: SHC_3BB0A8C1_0x00534D10 88.99% reg alloc differs --- .../selectUnitsInDragBoxForCurrentPlayer.cpp | 112 ++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 113 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/selectUnitsInDragBoxForCurrentPlayer.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/selectUnitsInDragBoxForCurrentPlayer.cpp b/src/OpenSHC/Map/Units/UnitsState/selectUnitsInDragBoxForCurrentPlayer.cpp new file mode 100644 index 000000000..1965b300e --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/selectUnitsInDragBoxForCurrentPlayer.cpp @@ -0,0 +1,112 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Map/Units/States/UnitState.hpp" +#include "OpenSHC/Map/Units/UnitLogicState.hpp" +#include "OpenSHC/Map/Units/UnitType.hpp" + +#include "OpenSHC/Globals/DAT_CurrentUnitSlotID.hpp" +#include "OpenSHC/Globals/DAT_GameSynchronyState.hpp" +#include "OpenSHC/Globals/DAT_MouseState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Map::Units::UnitLogicState; + using OpenSHC::Map::Units::UnitType; + using OpenSHC::Map::Units::States::UnitState; + + // FUNCTION: STRONGHOLDCRUSADER 0x00534D10 + void UnitsState::selectUnitsInDragBoxForCurrentPlayer() + { + LONG _boxLeft; + LONG _boxRight; + if (DAT_MouseState::instance.selectionBox.right < DAT_MouseState::instance.selectionBox.left) { + _boxLeft = DAT_MouseState::instance.selectionBox.right; + _boxRight = DAT_MouseState::instance.selectionBox.left; + } else { + _boxLeft = DAT_MouseState::instance.selectionBox.left; + _boxRight = DAT_MouseState::instance.selectionBox.right; + } + LONG _boxTop; + LONG _boxBottom; + if (DAT_MouseState::instance.selectionBox.bottom < DAT_MouseState::instance.selectionBox.top) { + _boxTop = DAT_MouseState::instance.selectionBox.bottom; + _boxBottom = DAT_MouseState::instance.selectionBox.top; + } else { + _boxTop = DAT_MouseState::instance.selectionBox.top; + _boxBottom = DAT_MouseState::instance.selectionBox.bottom; + } + this->totalUnitsInSelection = 0; + for (DAT_CurrentUnitSlotID::instance = 1; (int)DAT_CurrentUnitSlotID::instance < (int)this->maxUnitCount; + DAT_CurrentUnitSlotID::instance = DAT_CurrentUnitSlotID::instance + 1) { + this->units[DAT_CurrentUnitSlotID::instance].isSelected = 0; + if (this->units[DAT_CurrentUnitSlotID::instance].logicalState != OpenSHC::Map::Units::ULS_NORMAL) { + continue; + } + if (this->units[DAT_CurrentUnitSlotID::instance].dying != 0) { + continue; + } + if (this->units[DAT_CurrentUnitSlotID::instance].isSelectable_OR_matchTime == 0) { + continue; + } + if (this->units[DAT_CurrentUnitSlotID::instance].unknownTestAgainst0_2 != 0) { + continue; + } + if (this->units[DAT_CurrentUnitSlotID::instance].state.generic + == OpenSHC::Map::Units::States::US_JESTER_ROAM_TO) { + continue; + } + if (this->units[DAT_CurrentUnitSlotID::instance].ifSelectedThenPlayerID + != DAT_GameSynchronyState::instance.currentPlayerSlotID) { + if (this->units[DAT_CurrentUnitSlotID::instance].drawX == 0 + && this->units[DAT_CurrentUnitSlotID::instance].drawY == 0) { + continue; + } + if (this->units[DAT_CurrentUnitSlotID::instance].drawX + + this->units[DAT_CurrentUnitSlotID::instance].drawXOffset + >= _boxRight) { + continue; + } + if (this->units[DAT_CurrentUnitSlotID::instance].drawY + + this->units[DAT_CurrentUnitSlotID::instance].someDrawYOffset + >= _boxBottom) { + continue; + } + if (this->units[DAT_CurrentUnitSlotID::instance].spriteWidthUnk + + this->units[DAT_CurrentUnitSlotID::instance].drawX + + this->units[DAT_CurrentUnitSlotID::instance].drawXOffset + < _boxLeft) { + continue; + } + if (this->units[DAT_CurrentUnitSlotID::instance].spriteHeightUnk + + this->units[DAT_CurrentUnitSlotID::instance].drawY + + this->units[DAT_CurrentUnitSlotID::instance].someDrawYOffset + < _boxTop) { + continue; + } + if (this->units[DAT_CurrentUnitSlotID::instance].unitType == OpenSHC::Map::Units::UT_S_TOWER + && this->units[DAT_CurrentUnitSlotID::instance].state.generic + == (OpenSHC::Map::Units::States::US_STAND_UPUnk + | OpenSHC::Map::Units::States::US_IDLEUnk)) { + continue; + } + if (this->units[DAT_CurrentUnitSlotID::instance].unitType == OpenSHC::Map::Units::UT_TUNNELER + && (this->units[DAT_CurrentUnitSlotID::instance].state.generic + == OpenSHC::Map::Units::States::US_LOOK_AROUNDUnk + || this->units[DAT_CurrentUnitSlotID::instance].state.generic + == OpenSHC::Map::Units::States::US_STAND_UPUnk)) { + continue; + } + } + if (this->units[DAT_CurrentUnitSlotID::instance].owner + == DAT_GameSynchronyState::instance.currentPlayerSlotID + && this->units[DAT_CurrentUnitSlotID::instance].unitType != OpenSHC::Map::Units::UT_LORD) { + this->units[DAT_CurrentUnitSlotID::instance].isSelected = 1; + this->totalUnitsInSelection = this->totalUnitsInSelection + 1; + } + } + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 5b53d59bb..ffd5f44c1 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -50845,7 +50845,7 @@ SHC_3BB0A8C1_0x00534D08 | 0.0% | Pending SHC_3BB0A8C1_0x00534D0C | 0.0% | Pending -SHC_3BB0A8C1_0x00534D10 | 0.0% | Pending +SHC_3BB0A8C1_0x00534D10 | 89.0% | reg alloc differs SHC_3BB0A8C1_0x00534D80 | 0.0% | Pending From e1fc1689cd92f0162d244659b0b5bc0ad7733ca1 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:55 +0200 Subject: [PATCH 158/299] reimplement: SHC_3BB0A8C1_0x0052EC10 100.00% Reimplemented --- .../Map/Units/UnitsState/nonEuroRecruit.cpp | 103 ++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 104 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/nonEuroRecruit.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/nonEuroRecruit.cpp b/src/OpenSHC/Map/Units/UnitsState/nonEuroRecruit.cpp new file mode 100644 index 000000000..1db8a6d18 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/nonEuroRecruit.cpp @@ -0,0 +1,103 @@ +#include "OpenSHC/Map/Units/TribesState.func.hpp" +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Map/Units/States/UnitState.hpp" +#include "OpenSHC/Map/Units/UnitLogicState.hpp" +#include "OpenSHC/Map/Units/UnitType.hpp" + +#include "OpenSHC/Globals/DAT_GameState.hpp" +#include "OpenSHC/Globals/DAT_GameSynchronyState.hpp" +#include "OpenSHC/Globals/DAT_TribesState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Map::Units::UnitLogicState; + using OpenSHC::Map::Units::UnitType; + using OpenSHC::Map::Units::States::UnitState; + + // FUNCTION: STRONGHOLDCRUSADER 0x0052EC10 + int UnitsState::nonEuroRecruit(UnitType unitType, undefined4 recruitmentBuilding, int playerID, int param_4) + { + this->euroUnitAcquisitionFailReason = 0; + int _unitCost; + if (unitType == OpenSHC::Map::Units::UT_E_ENGINEER) { + _unitCost = 0x1e; + } else if (unitType == OpenSHC::Map::Units::UT_TUNNELER) { + _unitCost = 0x1e; + } else if (unitType == OpenSHC::Map::Units::UT_E_LADDER) { + _unitCost = 4; + } else if (unitType == OpenSHC::Map::Units::UT_E_MONK) { + _unitCost = 10; + } else if (unitType == OpenSHC::Map::Units::UT_A_ARCHER) { + _unitCost = 0x4b; + } else if (unitType == OpenSHC::Map::Units::UT_A_SLAVE) { + _unitCost = 5; + } else if (unitType == OpenSHC::Map::Units::UT_A_SLINGER) { + _unitCost = 0xc; + } else if (unitType == OpenSHC::Map::Units::UT_A_ASSASSIN) { + _unitCost = 0x3c; + } else if (unitType == OpenSHC::Map::Units::UT_A_HARCHER) { + _unitCost = 0x50; + } else if (unitType == OpenSHC::Map::Units::UT_A_SWORDSMAN) { + _unitCost = 0x50; + } else if (unitType == OpenSHC::Map::Units::UT_A_FIRETHROWER) { + _unitCost = 100; + } else { + return 0; + } + /* Check if player has enough gold, then convert peasant to new unit */ + if (DAT_GameState::instance.playerDataArray[playerID].currentResources[0xf] < _unitCost) { + this->euroUnitAcquisitionFailReason = 1; + return 0; + } + for (int unitID = 1; unitID < (int)this->maxUnitCount; ++unitID) { + if (this->units[unitID].unitType != OpenSHC::Map::Units::UT_PEASANT) { + continue; + } + if (this->units[unitID].owner != playerID) { + continue; + } + if (this->units[unitID].dying != 0) { + continue; + } + if (this->units[unitID].logicalState != OpenSHC::Map::Units::ULS_NORMAL) { + continue; + } + if (this->units[unitID].state.generic == OpenSHC::Map::Units::States::US_RELOAD_WEAPONUnk) { + continue; + } + if (this->units[unitID].state.generic == OpenSHC::Map::Units::States::US_AIM_WEAPONUnk) { + continue; + } + if (this->units[unitID].state.generic == OpenSHC::Map::Units::States::US_JESTER_ROAM_TO) { + continue; + } + if (this->units[unitID].state.generic == OpenSHC::Map::Units::States::US_MELEE_ATTACK) { + continue; + } + if (param_4 != 0) { + return 1; + } + this->units[unitID].unitTypeToChangeInto = (UnitTypeShort)unitType; + this->units[unitID].state_2 = 0; + this->units[unitID].state.generic = OpenSHC::Map::Units::States::US_JESTER_ROAM_TO; + this->units[unitID].disappearFadeAlphaCountdown = 0; + this->units[unitID].engineerManningSiegeStateRef_checkType = 1; + this->units[unitID].cachedState = OpenSHC::Map::Units::States::US_DETERMINE_NEXT_STATEUnk; + this->units[unitID].isDisappearingUnk = 1; + this->units[unitID].workplaceBuildingID_1 = (short)recruitmentBuilding; + this->units[unitID].resourceToDeposit = 0; + DAT_GameState::instance.playerDataArray[playerID].currentResources[0xf] -= _unitCost; + DAT_GameSynchronyState::instance.finalResults.finalTroopsProduced[playerID] += 1; + MACRO_CALL_MEMBER(OpenSHC::Map::Units::TribesState_Func::aiAssignNewUnitToTribe, DAT_TribesState::ptr)( + playerID, unitType, unitID); + return unitID; + } + this->euroUnitAcquisitionFailReason = 3; + return 0; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index ffd5f44c1..0935b993c 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -49309,7 +49309,7 @@ SHC_3BB0A8C1_0x0052E830 | 89.5% | orig walks unit ptr SHC_3BB0A8C1_0x0052E960 | 0.0% | Pending -SHC_3BB0A8C1_0x0052EC10 | 0.0% | Pending +SHC_3BB0A8C1_0x0052EC10 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0052EDC0 | 48.5% | branch shape differs From bd9d1121557379d10428584c4d085adb2a95a690 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:56 +0200 Subject: [PATCH 159/299] reimplement: SHC_3BB0A8C1_0x00536A60 87.31% array init loop differs --- .../selectionContainsCombatUnit.cpp | 162 ++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 163 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/selectionContainsCombatUnit.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/selectionContainsCombatUnit.cpp b/src/OpenSHC/Map/Units/UnitsState/selectionContainsCombatUnit.cpp new file mode 100644 index 000000000..92b6b0f77 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/selectionContainsCombatUnit.cpp @@ -0,0 +1,162 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Map/Units/UnitLogicState.hpp" + +#include "OpenSHC/Globals/DAT_CurrentUnitSlotID.hpp" +#include "OpenSHC/Globals/DAT_GameSynchronyState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Map::Units::UnitLogicState; + + // FUNCTION: STRONGHOLDCRUSADER 0x00536A60 + int UnitsState::selectionContainsCombatUnit(uint unitID) + { + /* create a unittype array of length 80 and initialize it with 0's */ + uint selectedUnitsMap[80]; + for (int i = 0; i < 80; ++i) { + selectedUnitsMap[i] = 0; + } + /* for every unit in the game, we check whether it is owned by the current + player, whether the unit has 3 properties, and whether it has not been + mentioned in the size 80 array. Then, we put that ID at that location. + + map */ + bool _hasMatch = false; + for (DAT_CurrentUnitSlotID::instance = unitID; + (int)DAT_CurrentUnitSlotID::instance < (int)this->maxUnitCount; + DAT_CurrentUnitSlotID::instance = DAT_CurrentUnitSlotID::instance + 1) { + if (this->units[DAT_CurrentUnitSlotID::instance].logicalState == OpenSHC::Map::Units::ULS_NORMAL + && this->units[DAT_CurrentUnitSlotID::instance].dying == 0 + && this->units[DAT_CurrentUnitSlotID::instance].owner + == DAT_GameSynchronyState::instance.currentPlayerSlotID + && this->units[DAT_CurrentUnitSlotID::instance].isSelected != 0 + && selectedUnitsMap[(short)this->units[DAT_CurrentUnitSlotID::instance].unitType] == 0) { + selectedUnitsMap[(short)this->units[DAT_CurrentUnitSlotID::instance].unitType] + = DAT_CurrentUnitSlotID::instance; + _hasMatch = true; + } + } + /* if we have at least 1 match, return it. the order of returning seems really + arbitrary, but maybe it means something */ + if (!_hasMatch) { + return -1; + } + /* E_ARCHER */ + if (selectedUnitsMap[0x16] != 0) { + return selectedUnitsMap[0x16]; + } + if (selectedUnitsMap[0x26] != 0) { + return selectedUnitsMap[0x26]; + } + /* E_XBOW */ + if (selectedUnitsMap[0x17] != 0) { + return selectedUnitsMap[0x17]; + } + /* A_ARCHER */ + if (selectedUnitsMap[0x46] != 0) { + return selectedUnitsMap[0x46]; + } + /* A_HARCHER */ + if (selectedUnitsMap[0x4a] != 0) { + return selectedUnitsMap[0x4a]; + } + /* A_SLINGER */ + if (selectedUnitsMap[0x48] != 0) { + return selectedUnitsMap[0x48]; + } + /* A_FIRETHROWER */ + if (selectedUnitsMap[0x4c] != 0) { + return selectedUnitsMap[0x4c]; + } + /* S_FBALLISTA */ + if (selectedUnitsMap[0x4d] != 0) { + return selectedUnitsMap[0x4d]; + } + /* S_CATAPULT */ + if (selectedUnitsMap[0x27] != 0) { + return selectedUnitsMap[0x27]; + } + /* S_TREBUCHET */ + if (selectedUnitsMap[0x28] != 0) { + return selectedUnitsMap[0x28]; + } + /* S_MANGONEL */ + if (selectedUnitsMap[0x29] != 0) { + return selectedUnitsMap[0x29]; + } + /* S_BALLISTA */ + if (selectedUnitsMap[0x3d] != 0) { + return selectedUnitsMap[0x3d]; + } + /* E_SPEARMAN */ + if (selectedUnitsMap[0x18] != 0) { + return selectedUnitsMap[0x18]; + } + /* E_PIKEMAN */ + if (selectedUnitsMap[0x19] != 0) { + return selectedUnitsMap[0x19]; + } + /* E_MACEMAN */ + if (selectedUnitsMap[0x1a] != 0) { + return selectedUnitsMap[0x1a]; + } + /* E_SWORDSMAN */ + if (selectedUnitsMap[0x1b] != 0) { + return selectedUnitsMap[0x1b]; + } + /* E_KNIGHT */ + if (selectedUnitsMap[0x1c] != 0) { + return selectedUnitsMap[0x1c]; + } + /* TUNNELER */ + if (selectedUnitsMap[5] != 0) { + return selectedUnitsMap[5]; + } + /* E_LADDERMAN */ + if (selectedUnitsMap[0x1d] != 0) { + return selectedUnitsMap[0x1d]; + } + /* E_ENGINEER */ + if (selectedUnitsMap[0x1e] != 0) { + return selectedUnitsMap[0x1e]; + } + /* E_MONK */ + if (selectedUnitsMap[0x25] != 0) { + return selectedUnitsMap[0x25]; + } + /* A_SLAVE */ + if (selectedUnitsMap[0x47] != 0) { + return selectedUnitsMap[0x47]; + } + /* A_ASSASSIN */ + if (selectedUnitsMap[0x49] != 0) { + return selectedUnitsMap[0x49]; + } + /* A_SWORDSMAN */ + if (selectedUnitsMap[0x4b] != 0) { + return selectedUnitsMap[0x4b]; + } + /* LORD */ + if (selectedUnitsMap[0x37] != 0) { + return selectedUnitsMap[0x37]; + } + /* S_TOWER */ + if (selectedUnitsMap[0x3a] != 0) { + return selectedUnitsMap[0x3a]; + } + /* S_BATTERINGRAM */ + if (selectedUnitsMap[0x3b] != 0) { + return selectedUnitsMap[0x3b]; + } + /* S_SHIELD */ + if (selectedUnitsMap[0x3c] != 0) { + return selectedUnitsMap[0x3c]; + } + return -1; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 0935b993c..9218e9df1 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -51201,7 +51201,7 @@ SHC_3BB0A8C1_0x00536A50 | 0.0% | Pending SHC_3BB0A8C1_0x00536A51 | 0.0% | Pending -SHC_3BB0A8C1_0x00536A60 | 0.0% | Pending +SHC_3BB0A8C1_0x00536A60 | 87.3% | array init loop differs SHC_3BB0A8C1_0x00536C70 | 100.0% | Reimplemented From e627f692031693d84d60bb87be67f96a7c700935 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:56 +0200 Subject: [PATCH 160/299] reimplement: SHC_3BB0A8C1_0x0053B8E0 83.61% orig caches many locals --- .../Map/Units/UnitsState/setUnitValues.cpp | 85 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 86 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/setUnitValues.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/setUnitValues.cpp b/src/OpenSHC/Map/Units/UnitsState/setUnitValues.cpp new file mode 100644 index 000000000..c0f7a7df0 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/setUnitValues.cpp @@ -0,0 +1,85 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Map/Units/UnitType.hpp" + +#include "OpenSHC/Globals/DAT_TextureRenderCoreObject.hpp" +#include "OpenSHC/Globals/DAT_UnitPropertiesDefinedData.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Map::Units::UnitType; + + // FUNCTION: STRONGHOLDCRUSADER 0x0053B8E0 + void UnitsState::setUnitValues(int unitID, UnitType unitType) + { + this->units[unitID].unitType = (UnitTypeShort)unitType; + this->units[unitID].field64_0x90 = (short)DAT_UnitPropertiesDefinedData::instance.field65_0x7634[unitType]; + this->units[unitID].isStalked = (byte)DAT_UnitPropertiesDefinedData::instance.field66_0x7774[unitType]; + this->units[unitID].gmIDUnk = (short)DAT_UnitPropertiesDefinedData::instance.SPRITE_ID[unitType]; + this->units[unitID].spriteID = (short)DAT_UnitPropertiesDefinedData::instance.SPRITE_ID[unitType]; + this->units[unitID].gfxNumber = 1; + this->units[unitID].field22_0x2a = (short)DAT_TextureRenderCoreObject::instance + .gmFileHeaderColorpaletteArray[this->units[unitID].spriteID] + .originX; + *(short*)&this->units[unitID].unknownV = (short)DAT_TextureRenderCoreObject::instance + .gmFileHeaderColorpaletteArray[this->units[unitID].spriteID] + .originY; + this->units[unitID].spriteWidthUnk + = (short)DAT_UnitPropertiesDefinedData::instance.UNIT_SPRITE_DIMENSIONS[unitType][0]; + this->units[unitID].spriteHeightUnk + = (short)DAT_UnitPropertiesDefinedData::instance.UNIT_SPRITE_DIMENSIONS[unitType][1]; + this->units[unitID].drawXOffset = this->units[unitID].field22_0x2a - this->units[unitID].spriteWidthUnk / 2; + this->units[unitID].someDrawYOffset + = ((short)this->units[unitID].unknownV - this->units[unitID].spriteHeightUnk) + 3; + this->units[unitID].movementSpeed + = (short)DAT_UnitPropertiesDefinedData::instance.UNIT_MOVEMENT_SPEED_ARRAY[unitType]; + this->units[unitID].calculatedMovementSpeed = this->units[unitID].movementSpeed; + this->units[unitID].field200_0x354 = 0; + this->units[unitID].field199_0x350 = 0; + this->units[unitID].maxHealth = DAT_UnitPropertiesDefinedData::instance.BASE_HP[unitType]; + this->units[unitID].health = this->units[unitID].maxHealth; + if (this->units[unitID].maxHealth == 0) { + this->units[unitID].healthPercentage = 100; + } else { + this->units[unitID].healthPercentage + = (short)((this->units[unitID].health * 100) / this->units[unitID].maxHealth); + } + byte _firstNameIndex = this->units[unitID].firstNameIndex; + this->units[unitID].healthbar = this->units[unitID].healthPercentage / 10; + this->units[unitID].unitCanClimb = (short)DAT_UnitPropertiesDefinedData::instance.UNIT_CLIMB[unitType]; + this->units[unitID].someUnitStat4 + = (short)DAT_UnitPropertiesDefinedData::instance.SomeUnitStatMatrix4[unitType]; + this->units[unitID].graphicSize = (short)DAT_UnitPropertiesDefinedData::instance.GRAPHIC_SIZE[unitType]; + this->units[unitID].someUnitStat2_meleeDamageUnk + = (short)DAT_UnitPropertiesDefinedData::instance.UNIT_CAN_MELEE[unitType]; + this->units[unitID].enemyNoticeFrequencyUnk + = DAT_UnitPropertiesDefinedData::instance.UNIT_ENEMY_NOTICE_RANGE[unitType]; + this->units[unitID].moveableUnk = (short)DAT_UnitPropertiesDefinedData::instance.UNIT_MOVABLE[unitType]; + if ((char)_firstNameIndex < '\x01' || unitType == OpenSHC::Map::Units::UT_BREWER + || unitType == OpenSHC::Map::Units::UT_TANNER || unitType == OpenSHC::Map::Units::UT_LADY + || unitType == OpenSHC::Map::Units::UT_MOTHER || unitType == OpenSHC::Map::Units::UT_JUGGLER + || unitType == OpenSHC::Map::Units::UT_FIREEATER || unitType == OpenSHC::Map::Units::UT_PRIEST) { + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::assignNameToUnit, this)(unitID); + } + if (this->units[unitID].owner < 1) { + this->units[unitID].occupancyOrFlag = 0xff; + this->units[unitID].field258_0x3d1 = 0xff; + } else { + this->units[unitID].occupancyOrFlag = '\x01' << ((char)this->units[unitID].owner - 1U & 0x1f); + this->units[unitID].field258_0x3d1 = ~this->units[unitID].occupancyOrFlag; + } + this->units[unitID].isSelectable_OR_matchTime = 0; + this->units[unitID].field316_0x430 = 0; + if (unitType != OpenSHC::Map::Units::UT_CAGEDOG) { + this->units[unitID].unknownBool01 = 500; + } + /* Assassin */ + if (unitType == OpenSHC::Map::Units::UT_A_ASSASSIN) { + this->units[unitID].assassinsMicroDistanceToEnemyUnk = 32000; + } + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 9218e9df1..aec5db39f 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -59651,7 +59651,7 @@ SHC_3BB0A8C1_0x0053B800 | 0.0% | Pending SHC_3BB0A8C1_0x0053B8B0 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x0053B8E0 | 0.0% | Pending +SHC_3BB0A8C1_0x0053B8E0 | 83.6% | orig caches many locals SHC_3BB0A8C1_0x0053BB10 | 100.0% | Reimplemented From 11cc28e8539d9690346edd39432adf9ffcdd68ac Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:56 +0200 Subject: [PATCH 161/299] reimplement: SHC_3BB0A8C1_0x00532460 66.24% branch shape differs --- .../UnitsState/processFireDamageToUnit.cpp | 126 ++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 127 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/processFireDamageToUnit.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/processFireDamageToUnit.cpp b/src/OpenSHC/Map/Units/UnitsState/processFireDamageToUnit.cpp new file mode 100644 index 000000000..41ccac893 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/processFireDamageToUnit.cpp @@ -0,0 +1,126 @@ +#include "OpenSHC/Audio/SFX/SFXState.func.hpp" +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Random/RNG.func.hpp" +#include "OpenSHC/DE/SHCDE/eSFX.hpp" +#include "OpenSHC/Map/Units/States/UnitState.hpp" +#include "OpenSHC/Map/Units/UnitLogicState.hpp" +#include "OpenSHC/Map/Units/UnitType.hpp" + +#include "OpenSHC/Globals/DAT_SFXState.hpp" +#include "OpenSHC/Globals/SEC_RNG.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::DE::SHCDE::eSFX; + using OpenSHC::Map::Units::UnitLogicState; + using OpenSHC::Map::Units::UnitType; + using OpenSHC::Map::Units::States::UnitState; + + // FUNCTION: STRONGHOLDCRUSADER 0x00532460 + undefined4 UnitsState::processFireDamageToUnit(int unitID, int playerID, int halfTheDamage) + { + if (unitID < 1) { + return 0; + } + if (this->units[unitID].dying != 0) { + return 0; + } + UnitTypeShort _unitType = this->units[unitID].unitType; + uint _damage; + if (_unitType == OpenSHC::Map::Units::UT_LORD) { + _damage = 25; + } else if (_unitType == OpenSHC::Map::Units::UT_FIREFIGHTER) { + _damage = 1; + } else if (_unitType == OpenSHC::Map::Units::UT_A_FIRETHROWER) { + _damage = 10; + } else { + _damage = 100; + } + if (halfTheDamage != 0) { + _damage = _damage / 2; + } + if (playerID != 0 && playerID != this->units[unitID].owner) { + this->units[unitID].lastEncounteredEnemyPlayerID = (short)playerID; + this->units[unitID].lastEncounteredEnemyUnitIDUnk = 0; + } + this->units[unitID].health = this->units[unitID].health - _damage; + if (this->units[unitID].health < 1) { + this->units[unitID].health = 0; + } + if (this->units[unitID].maxHealth == 0) { + this->units[unitID].healthPercentage = 100; + } else { + this->units[unitID].healthPercentage + = (short)((this->units[unitID].health * 100) / this->units[unitID].maxHealth); + } + this->units[unitID].healthbar = this->units[unitID].healthPercentage / 10; + if (this->units[unitID].health > 0) { + return 1; + } + this->units[unitID].animationCycleNumber = 0; + this->units[unitID].field323_0x442 = 1; + if (_unitType == OpenSHC::Map::Units::UT_LORD) { + this->units[unitID].dying = 1; + this->units[unitID].tunnelerFinishedDigging = 1; + this->units[unitID].health = 0; + this->units[unitID].animationCycleNumber = 0; + this->units[unitID].state.generic = OpenSHC::Map::Units::States::US_STONE_DEATH_01; + return 1; + } + this->units[unitID].logicalState = OpenSHC::Map::Units::ULS_TRANSITIONING; + this->units[unitID].state_2 = 0; + switch (_unitType) { + case OpenSHC::Map::Units::UT_ANTELOPESHDEER: + if (this->units[unitID].antelopeBasedRngValue == 2) { + this->units[unitID].unitTypeToChangeInto = OpenSHC::Map::Units::UT_BURNING_ANIMAL_SMALL; + this->units[unitID].state_2 = 1; + break; + } + this->units[unitID].unitTypeToChangeInto = OpenSHC::Map::Units::UT_BURNING_ANIMAL_BIG; + this->units[unitID].state_2 = 1; + break; + case OpenSHC::Map::Units::UT_QUARRYOX: + case OpenSHC::Map::Units::UT_LIONSHWOLF: + case OpenSHC::Map::Units::UT_CAMELSHBEAR: + case OpenSHC::Map::Units::UT_COW: + case OpenSHC::Map::Units::UT_CAGEDOG: + this->units[unitID].unitTypeToChangeInto = OpenSHC::Map::Units::UT_BURNING_ANIMAL_BIG; + this->units[unitID].state_2 = 1; + break; + case OpenSHC::Map::Units::UT_RABBIT: + case OpenSHC::Map::Units::UT_HUNTERDOG: + case OpenSHC::Map::Units::UT_CHICKEN: + this->units[unitID].unitTypeToChangeInto = OpenSHC::Map::Units::UT_BURNING_ANIMAL_SMALL; + this->units[unitID].state_2 = 1; + break; + default: + this->units[unitID].unitTypeToChangeInto = OpenSHC::Map::Units::UT_BURNINGMAN; + } + if (this->units[unitID].isStalked != 0) { + return 1; + } + /* if a male */ + if (_unitType != OpenSHC::Map::Units::UT_BREWER && _unitType != OpenSHC::Map::Units::UT_TANNER + && _unitType != OpenSHC::Map::Units::UT_LADY && _unitType != OpenSHC::Map::Units::UT_MOTHER + && (_unitType != OpenSHC::Map::Units::UT_CHILD || this->units[unitID].spriteID != 0x81)) { + MACRO_CALL_MEMBER(OpenSHC::Random::RNG_Func::nextRandomNumber1, SEC_RNG::ptr)(); + if (((byte)SEC_RNG::instance.currentNumber1 & 1) == 0) { + MACRO_CALL_MEMBER(OpenSHC::Audio::SFX::SFXState_Func::playSFXAtLocation, DAT_SFXState::ptr)( + this->units[unitID].x, this->units[unitID].y, OpenSHC::DE::SHCDE::FX_MAN_BURN2); + return 1; + } + MACRO_CALL_MEMBER(OpenSHC::Audio::SFX::SFXState_Func::playSFXAtLocation, DAT_SFXState::ptr)( + this->units[unitID].x, this->units[unitID].y, OpenSHC::DE::SHCDE::FX_MAN_BURN); + return 1; + } + /* if female */ + MACRO_CALL_MEMBER(OpenSHC::Audio::SFX::SFXState_Func::playSFXAtLocation, DAT_SFXState::ptr)( + this->units[unitID].x, this->units[unitID].y, OpenSHC::DE::SHCDE::FX_GIRL_SCREAM); + return 1; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index aec5db39f..4a6dde7f7 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -50331,7 +50331,7 @@ SHC_3BB0A8C1_0x0053245D | 0.0% | Pending SHC_3BB0A8C1_0x0053245E | 0.0% | Pending -SHC_3BB0A8C1_0x00532460 | 0.0% | Pending +SHC_3BB0A8C1_0x00532460 | 66.2% | branch shape differs SHC_3BB0A8C1_0x005326A8 | 0.0% | Pending From 3c50499710ceeb780b4527595de7baed8dd13ad8 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:57 +0200 Subject: [PATCH 162/299] reimplement: SHC_3BB0A8C1_0x005330A0 81.58% switch fallthrough differs --- .../UnitsState/setRandomShootLocation.cpp | 123 ++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 124 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/setRandomShootLocation.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/setRandomShootLocation.cpp b/src/OpenSHC/Map/Units/UnitsState/setRandomShootLocation.cpp new file mode 100644 index 000000000..8b94794f7 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/setRandomShootLocation.cpp @@ -0,0 +1,123 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Random/RNG.func.hpp" +#include "OpenSHC/Map/Units/UnitInstructionType.hpp" +#include "OpenSHC/Map/Units/UnitType.hpp" + +#include "OpenSHC/Globals/SEC_RNG.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Map::Units::UnitInstructionType; + using OpenSHC::Map::Units::UnitType; + + // FUNCTION: STRONGHOLDCRUSADER 0x005330A0 + void UnitsState::setRandomShootLocation(int unitID, int microX, int microY, int z) + { + int _distanceX; + if (this->units[unitID].microXPosition < microX) { + _distanceX = microX - this->units[unitID].microXPosition; + } else { + _distanceX = this->units[unitID].microXPosition - microX; + } + int _distance; + if (this->units[unitID].microYPosition < microY) { + _distance = microY - this->units[unitID].microYPosition; + } else { + _distance = this->units[unitID].microYPosition - microY; + } + if (_distance <= _distanceX) { + _distance = _distanceX; + } + int _rng = SEC_RNG::instance.currentNumber2; + MACRO_CALL_MEMBER(OpenSHC::Random::RNG_Func::nextRandomNumber2, SEC_RNG::ptr)(); + int _spreadAlong; + int _spreadAcross; + if (this->units[unitID].unitType == OpenSHC::Map::Units::UT_S_TREBUCHET) { + _spreadAlong = 0; + if ((_rng & 3) == 0) { + _spreadAlong = _rng % 0x60 + -0x30; + } + _spreadAcross = (_rng / 256) % 0x60 + -0x30; + z = z + -0x10 + (_rng / 128) % 0x20; + } else if (this->units[unitID].unitType == OpenSHC::Map::Units::UT_S_CATAPULT) { + _spreadAlong = _rng % 0x80 - 0x60; + _spreadAcross = (_rng / 256) % 0x60 + -0x30; + z = z + -0x30 + (_rng / 128) % 0x40; + } else if (this->units[unitID].unitType == OpenSHC::Map::Units::UT_S_MANGONEL) { + _spreadAlong = _rng % 0xe0 + -0x70; + _spreadAcross = (_rng / 256) % 0x80 - 0x40; + z = z + -0x40 + (_rng / 128) % 0x80; + } else if (this->units[unitID].unitType == OpenSHC::Map::Units::UT_S_BALLISTA) { + if (this->units[unitID].targetingType == OpenSHC::Map::Units::UIT_ATTACK_LAND) { + _spreadAlong = _rng % 0x20 - 0x18; + _spreadAcross = (_rng / 256) % 0x28 + -0x14; + z = z + -0x14 + (_rng / 128) % 0x28; + } else { + _spreadAlong = 0; + _spreadAcross = 0; + } + } else if (this->units[unitID].unitType == OpenSHC::Map::Units::UT_S_FBALLISTA + && this->units[unitID].targetingType != OpenSHC::Map::Units::UIT_ATTACK_LAND) { + _spreadAlong = 0; + _spreadAcross = 0; + z = z + (_rng / 128) % 0x1e; + } else { + _spreadAlong = _rng % 0x60 + -0x30; + _spreadAcross = (_rng / 256) % 0x50 + -0x28; + z = z + -0x28 + (_rng / 128) % 0x50; + } + if (z < 8) { + z = 8; + } else if (z > 250) { + z = 250; + } + if (_distance / 2 < _spreadAlong) { + _spreadAlong = _spreadAlong / 2; + _spreadAcross = _spreadAcross / 2; + } + if (_distance < _spreadAlong) { + _spreadAlong = -_spreadAlong; + } + switch (this->units[unitID].facingDirection) { + case 0: + microY = microY + _spreadAlong; + microX = microX + _spreadAcross; + break; + case 1: + microX = microX + ((_spreadAcross * 3) / 4 - (_spreadAlong * 3) / 4); + microY = microY + (_spreadAlong * 3) / 4 + (_spreadAcross * 3) / 4; + break; + case 2: + microX = microX - _spreadAlong; + microY = microY + _spreadAcross; + break; + case 3: + microX = microX + (-((_spreadAlong * 3) / 4) - (_spreadAcross * 3) / 4); + microY = microY + ((_spreadAcross * 3) / 4 - (_spreadAlong * 3) / 4); + break; + case 4: + microY = microY - _spreadAlong; + microX = microX + _spreadAcross; + break; + case 5: + microX = microX + ((_spreadAlong * 3) / 4 - (_spreadAcross * 3) / 4); + microY = microY + (-((_spreadAcross * 3) / 4) - (_spreadAlong * 3) / 4); + break; + case 6: + microX = microX + _spreadAlong; + microY = microY + _spreadAcross; + break; + case 7: + microX = microX + (_spreadAlong * 3) / 4 + (_spreadAcross * 3) / 4; + microY = microY + ((_spreadAlong * 3) / 4 - (_spreadAcross * 3) / 4); + } + this->units[unitID].shootTargetZ = (short)z; + this->units[unitID].shootTargetMicroY = (short)microY; + this->units[unitID].shootTargetMicroX = (short)microX; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 4a6dde7f7..96662c7c7 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -50651,7 +50651,7 @@ SHC_3BB0A8C1_0x00533010 | 0.0% | Pending SHC_3BB0A8C1_0x00533090 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x005330A0 | 0.0% | Pending +SHC_3BB0A8C1_0x005330A0 | 81.6% | switch fallthrough differs SHC_3BB0A8C1_0x00533474 | 0.0% | Pending From 3aa5d7d100d3a2a559e09df675e9e6ebcbce3981 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:57 +0200 Subject: [PATCH 163/299] reimplement: SHC_3BB0A8C1_0x0053E440 46.10% orig walks unit ptr --- .../Map/Units/UnitsState/spawnUnit.cpp | 113 ++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 114 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/spawnUnit.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/spawnUnit.cpp b/src/OpenSHC/Map/Units/UnitsState/spawnUnit.cpp new file mode 100644 index 000000000..cc57c350d --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/spawnUnit.cpp @@ -0,0 +1,113 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Random/RNG.func.hpp" +#include "OpenSHC/Game/GameMode.hpp" +#include "OpenSHC/Map/Units/UnitInstructionType.hpp" +#include "OpenSHC/Map/Units/UnitLogicState.hpp" +#include "OpenSHC/Map/Units/UnitType.hpp" + +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_GameCore.hpp" +#include "OpenSHC/Globals/DAT_GameSynchronyState.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" +#include "OpenSHC/Globals/SEC_RNG.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Game::GameMode; + using OpenSHC::Map::Units::UnitInstructionType; + using OpenSHC::Map::Units::UnitLogicState; + using OpenSHC::Map::Units::UnitType; + + // FUNCTION: STRONGHOLDCRUSADER 0x0053E440 + int UnitsState::spawnUnit(int playerID, int displayColor, int microXPosition, int microYPosition, + int terrainHeight, UnitType unitType) + { + /* Loop until we find free slot. */ + int _unitID = 1; + for (; _unitID < 0x9c4; ++_unitID) { + if (this->units[_unitID].logicalState == OpenSHC::Map::Units::ULS_INVISIBLE) { + break; + } + if (_unitID > 0x9c2) { + return 0; + } + } + if ((int)this->maxUnitCount <= _unitID) { + this->maxUnitCount = _unitID + 1; + } + this->units[_unitID].uid = DAT_GameCore::instance.uniqueGameObjectTracker; + dword _time = DAT_GameCore::instance.mapTimeInTicks; + DAT_GameCore::instance.uniqueGameObjectTracker = DAT_GameCore::instance.uniqueGameObjectTracker + 1; + this->units[_unitID].logicalState = (UnitLogicState)1; + this->units[_unitID].owner = (short)playerID; + this->units[_unitID].terrainOrClimbHeight = (short)terrainHeight; + this->units[_unitID].microXPosition = (short)microXPosition + 4; + this->units[_unitID].time = _time; + this->units[_unitID].calculatedOwnerPlayerIndex = (short)displayColor; + this->units[_unitID].microYPosition = (short)microYPosition + 4; + this->units[_unitID].facingDirection = 0; + this->units[_unitID].displayColorPlayerID = (short)displayColor; + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::setUnitValues, this)(_unitID, unitType); + if (unitType == OpenSHC::Map::Units::UT_S_TOWER) { + this->units[_unitID].calculatedOwnerPlayerIndex = 0; + this->units[_unitID].displayColorPlayerID = 0; + } else if (unitType == OpenSHC::Map::Units::UT_CAGEDOG) { + this->units[_unitID].calculatedOwnerPlayerIndex = 0; + } + short _y + = (short)((this->units[_unitID].microYPosition + (this->units[_unitID].microYPosition >> 0x1f & 7U)) + >> 3); + this->units[_unitID].mimicCurrentYPosition = _y; + this->units[_unitID].y = _y; + this->units[_unitID].destinationY_2Unk = _y; + short _x + = (short)((this->units[_unitID].microXPosition + (this->units[_unitID].microXPosition >> 0x1f & 7U)) + >> 3); + this->units[_unitID].mimicCurrentXPosition = _x; + this->units[_unitID].x = _x; + this->units[_unitID].destinationX_2Unk = _x; + this->units[_unitID].movementRelated = 8; + this->units[_unitID].field105_0xe8 = 0; + this->units[_unitID].targetingType = (UnitInstructionType)0; + this->units[_unitID].tile = _x + DAT_ViewportRenderState::instance.translationMatrix[_y].addXgetTile; + this->units[_unitID].fixedRng = SEC_RNG::instance.currentNumber2; + MACRO_CALL_MEMBER(OpenSHC::Random::RNG_Func::nextRandomNumber2, SEC_RNG::ptr)(); + if (unitType == OpenSHC::Map::Units::UT_S_CATAPULT || unitType == OpenSHC::Map::Units::UT_S_TREBUCHET) { + if (DAT_GameSynchronyState::instance.currentPlayerFullIDArray[playerID] == -1) { + if (DAT_GameSynchronyState::instance.currentGameMode == OpenSHC::Game::GM_SOLITARY) { + this->units[_unitID].stoneAmmunition = 0x28; + } else { + this->units[_unitID].stoneAmmunition = 0x14; + } + } else { + this->units[_unitID].stoneAmmunition = 0x14; + } + } else if (unitType == OpenSHC::Map::Units::UT_S_MANGONEL) { + if (DAT_TileMapState::instance.BuildingLayer[this->units[_unitID].tile] != 0) { + DAT_BuildingsState::instance + .buildings[DAT_TileMapState::instance.BuildingLayer[this->units[_unitID].tile]] + .containsSiegeMangonel1OrBallista2 = 1; + } + } else if (unitType == OpenSHC::Map::Units::UT_S_BALLISTA) { + if (DAT_TileMapState::instance.BuildingLayer[this->units[_unitID].tile] != 0) { + DAT_BuildingsState::instance + .buildings[DAT_TileMapState::instance.BuildingLayer[this->units[_unitID].tile]] + .containsSiegeMangonel1OrBallista2 = 2; + } + } else if (unitType == OpenSHC::Map::Units::UT_CHILD) { + if ((this->units[_unitID].fixedRng & 0x80) != 0) { + this->units[_unitID].spriteID = 0x81; + } + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::assignNameToUnit, this)(_unitID); + } + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::commitPendingUnitPosition, this)(_unitID); + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::updateMicroPosition, this)(_unitID); + return _unitID; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 96662c7c7..3b79e05c3 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -60085,7 +60085,7 @@ SHC_3BB0A8C1_0x0053E384 | 0.0% | Pending SHC_3BB0A8C1_0x0053E390 | 55.2% | version ladder shape -SHC_3BB0A8C1_0x0053E440 | 0.0% | Pending +SHC_3BB0A8C1_0x0053E440 | 46.1% | orig walks unit ptr SHC_3BB0A8C1_0x0053E6C0 | 83.7% | branch shape differs From 46d5ccd5774e756189b54a9342c7d45eba9ef84e Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:58 +0200 Subject: [PATCH 164/299] reimplement: SHC_3BB0A8C1_0x0053A150 31.65% orig shares call tails --- .../getWorkerBlockingStateIfStuck.cpp | 206 ++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 207 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/getWorkerBlockingStateIfStuck.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/getWorkerBlockingStateIfStuck.cpp b/src/OpenSHC/Map/Units/UnitsState/getWorkerBlockingStateIfStuck.cpp new file mode 100644 index 000000000..dc37cbe17 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/getWorkerBlockingStateIfStuck.cpp @@ -0,0 +1,206 @@ +#include "OpenSHC/Map/Buildings/BuildingsState.func.hpp" +#include "OpenSHC/Map/LandscapeState.func.hpp" +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Game/Resources/ResourceType.hpp" +#include "OpenSHC/Map/Units/States/UnitState.hpp" + +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_CurrentUnitSlotID.hpp" +#include "OpenSHC/Globals/DAT_LandscapeState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Game::Resources::ResourceType; + using OpenSHC::Map::Units::States::UnitState; + + // FUNCTION: STRONGHOLDCRUSADER 0x0053A150 + int UnitsState::getWorkerBlockingStateIfStuck(int unitID) + { + if (this->units[unitID].dying != 0) { + return 0; + } + switch (this->units[unitID].unitType) { + case OpenSHC::Map::Units::UT_WOODCUTTER: + if (this->units[unitID].state.generic == OpenSHC::Map::Units::States::US_LOOK_AROUNDUnk) { + return 0x2f; + } + if (this->units[unitID].state.generic == (UnitState)10) { + if (MACRO_CALL_MEMBER(OpenSHC::Map::LandscapeState_Func::findTree, DAT_LandscapeState::ptr)( + this->units[unitID].owner, this->units[unitID].x, this->units[unitID].y) + != 0) { + return 0; + } + return 0x32; + } + break; + case OpenSHC::Map::Units::UT_FLETCHER: + if (this->units[unitID].state.generic == OpenSHC::Map::Units::States::US_FIRE_WEAPONUnk) { + return 0x31; + } + if (this->units[unitID].state.generic != OpenSHC::Map::Units::States::US_STAND_UPUnk) { + return 0; + } + if (MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::getStorageBuildingForResourceTypeAndAmount, + DAT_BuildingsState::ptr)(OpenSHC::Game::Resources::RT_WOOD, 1, this->units[unitID].owner) + != 0) { + return 0; + } + return 0x33; + case OpenSHC::Map::Units::UT_HUNTER: + if (this->units[unitID].state.generic == OpenSHC::Map::Units::States::US_RELOAD_WEAPONUnk) { + return 0x30; + } + if (this->units[unitID].state.generic == OpenSHC::Map::Units::States::US_LOOK_AROUNDUnk) { + if (MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::findNearestShootableDeer, this)(unitID) + != 0) { + return 0; + } + return 0x34; + } + break; + case OpenSHC::Map::Units::UT_QUARRYWORKER: + case OpenSHC::Map::Units::UT_PITCHMAN: + if (this->units[unitID].state.generic == (UnitState)2) { + return 0x2f; + } + break; + case OpenSHC::Map::Units::UT_WHEATFARMER: + if (this->units[unitID].state.generic + == (OpenSHC::Map::Units::States::US_STAND_UPUnk | OpenSHC::Map::Units::States::US_IDLEUnk)) { + return 0x2f; + } + break; + case OpenSHC::Map::Units::UT_HOPSFARMER: + if (this->units[unitID].state.generic == OpenSHC::Map::Units::States::US_LOOK_AROUNDUnk) { + return 0x2f; + } + break; + case OpenSHC::Map::Units::UT_APPLEFARMER: + if (this->units[unitID].state.generic == OpenSHC::Map::Units::States::US_FIRE_WEAPONUnk) { + return 0x30; + } + break; + case OpenSHC::Map::Units::UT_DAIRYFARMER: + if (this->units[unitID].state.generic == OpenSHC::Map::Units::States::US_RELOAD_WEAPONUnk) { + return 0x30; + } + break; + case OpenSHC::Map::Units::UT_MILLER: + if (this->units[unitID].state.generic == OpenSHC::Map::Units::States::US_IDLEUnk) { + if (MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::getStorageBuildingForResourceTypeAndAmount, + DAT_BuildingsState::ptr)(OpenSHC::Game::Resources::RT_WHEAT, 1, this->units[unitID].owner) + != 0) { + return 0; + } + return 0x35; + } + if (this->units[unitID].state.generic == OpenSHC::Map::Units::States::US_LOOK_AROUNDUnk) { + return 0x2f; + } + break; + case OpenSHC::Map::Units::UT_BAKER: + if ((short)this->units[unitID].state.generic < 0) { + break; + } + if ((short)this->units[unitID].state.generic < 2) { + if (MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::getBuildingResourceAmountByUid, + DAT_BuildingsState::ptr)(this->units[DAT_CurrentUnitSlotID::instance].workplaceBuildingID_1, + DAT_BuildingsState::instance + .buildings[this->units[DAT_CurrentUnitSlotID::instance].workplaceBuildingID_1] + .uid, + OpenSHC::Game::Resources::RT_FLOUR) + != 0) { + return 0; + } + return 0x36; + } + if (this->units[unitID].state.generic == OpenSHC::Map::Units::States::US_AIM_WEAPONUnk) { + return 0x30; + } + break; + case OpenSHC::Map::Units::UT_BREWER: + if (this->units[unitID].state.generic == OpenSHC::Map::Units::States::US_IDLEUnk) { + if (MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::getStorageBuildingForResourceTypeAndAmount, + DAT_BuildingsState::ptr)( + OpenSHC::Game::Resources::RT_HOPS, 1, this->units[DAT_CurrentUnitSlotID::instance].owner) + != 0) { + return 0; + } + return 0x37; + } + if (this->units[unitID].state.generic == OpenSHC::Map::Units::States::US_LOOK_AROUNDUnk) { + return 0x2f; + } + break; + case OpenSHC::Map::Units::UT_POLETURNER: + if (this->units[unitID].state.generic == OpenSHC::Map::Units::States::US_IDLEUnk) { + if (MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::getStorageBuildingForResourceTypeAndAmount, + DAT_BuildingsState::ptr)(OpenSHC::Game::Resources::RT_WOOD, 1, this->units[unitID].owner) + != 0) { + return 0; + } + return 0x33; + } + if (this->units[unitID].state.generic == OpenSHC::Map::Units::States::US_LOOK_AROUNDUnk) { + return 0x31; + } + break; + case OpenSHC::Map::Units::UT_SMITH: + case OpenSHC::Map::Units::UT_ARMORER: + if (this->units[unitID].state.generic != OpenSHC::Map::Units::States::US_IDLEUnk) { + if (this->units[unitID].state.generic == OpenSHC::Map::Units::States::US_LOOK_AROUNDUnk) { + return 0x31; + } + if (this->units[unitID].state.generic + != (OpenSHC::Map::Units::States::US_STAND_UPUnk | OpenSHC::Map::Units::States::US_IDLEUnk)) { + return 0; + } + } + if (MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::getStorageBuildingForResourceTypeAndAmount, + DAT_BuildingsState::ptr)(OpenSHC::Game::Resources::RT_IRON, 1, this->units[unitID].owner) + != 0) { + return 0; + } + return 0x38; + case OpenSHC::Map::Units::UT_TANNER: + if (this->units[unitID].state.generic == OpenSHC::Map::Units::States::US_IDLEUnk) { + if (MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::findNearestIdleCowForPlayer, this)( + this->units[unitID].owner, this->units[unitID].x, this->units[unitID].y) + != 0) { + return 0; + } + return 0x39; + } + if (this->units[unitID].state.generic == OpenSHC::Map::Units::States::US_LOOK_AROUNDUnk) { + return 0x31; + } + break; + case OpenSHC::Map::Units::UT_TRANSPORTMINER: + if (this->units[unitID].state.generic == (UnitState)3) { + return 0x2f; + } + break; + case OpenSHC::Map::Units::UT_INNKEEPER: + if (this->units[unitID].state.generic == OpenSHC::Map::Units::States::US_IDLEUnk) { + if (MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::getStorageBuildingForResourceTypeAndAmount, + DAT_BuildingsState::ptr)(OpenSHC::Game::Resources::RT_ALE, 1, this->units[unitID].owner) + != 0) { + return 0; + } + return 0x3a; + } + } + return 0; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 3b79e05c3..4d4ee9133 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -59507,7 +59507,7 @@ SHC_3BB0A8C1_0x0053A148 | 0.0% | Pending SHC_3BB0A8C1_0x0053A149 | 0.0% | Pending -SHC_3BB0A8C1_0x0053A150 | 0.0% | Pending +SHC_3BB0A8C1_0x0053A150 | 31.6% | orig shares call tails SHC_3BB0A8C1_0x0053A458 | 0.0% | Pending From ad8d56595beedc80ee55053e0192b375bd507a74 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:58 +0200 Subject: [PATCH 165/299] reimplement: SHC_3BB0A8C1_0x0053D9C0 19.24% orig shares branch tails --- .../Map/Units/UnitsState/getUnitInHitBox.cpp | 182 ++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 183 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/getUnitInHitBox.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/getUnitInHitBox.cpp b/src/OpenSHC/Map/Units/UnitsState/getUnitInHitBox.cpp new file mode 100644 index 000000000..5bcc93073 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/getUnitInHitBox.cpp @@ -0,0 +1,182 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Map/Units/States/UnitState.hpp" +#include "OpenSHC/Map/Units/UnitLogicState.hpp" +#include "OpenSHC/Map/Units/UnitType.hpp" + +#include "OpenSHC/Globals/DAT_CurrentUnitSlotID.hpp" +#include "OpenSHC/Globals/DAT_GameState.hpp" +#include "OpenSHC/Globals/DAT_GameSynchronyState.hpp" +#include "OpenSHC/Globals/DAT_MinimapViewState.hpp" +#include "OpenSHC/Globals/DAT_MouseState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Map::Units::UnitLogicState; + using OpenSHC::Map::Units::UnitType; + using OpenSHC::Map::Units::States::UnitState; + + // FUNCTION: STRONGHOLDCRUSADER 0x0053D9C0 + uint UnitsState::getUnitInHitBox(undefined4 param_1) + { + int _hitboxXStart; + int _hitboxXEnd; + if (DAT_MouseState::instance.hitboxXEnd < DAT_MouseState::instance.hitboxXStart) { + _hitboxXStart = DAT_MouseState::instance.hitboxXEnd; + _hitboxXEnd = DAT_MouseState::instance.hitboxXStart; + } else { + _hitboxXStart = DAT_MouseState::instance.hitboxXStart; + _hitboxXEnd = DAT_MouseState::instance.hitboxXEnd; + } + int _hitboxYStart; + int _hitboxYEnd; + if (DAT_MouseState::instance.hitboxYEnd < DAT_MouseState::instance.hitboxYStart) { + _hitboxYStart = DAT_MouseState::instance.hitboxYEnd; + _hitboxYEnd = DAT_MouseState::instance.hitboxYStart; + } else { + _hitboxYStart = DAT_MouseState::instance.hitboxYStart; + _hitboxYEnd = DAT_MouseState::instance.hitboxYEnd; + } + int _currentPlayerSlotID = DAT_GameSynchronyState::instance.currentPlayerSlotID; + for (DAT_CurrentUnitSlotID::instance = 1; (int)DAT_CurrentUnitSlotID::instance < (int)this->maxUnitCount; + DAT_CurrentUnitSlotID::instance = DAT_CurrentUnitSlotID::instance + 1) { + if (this->units[DAT_CurrentUnitSlotID::instance].logicalState != OpenSHC::Map::Units::ULS_NORMAL) { + continue; + } + if (this->units[DAT_CurrentUnitSlotID::instance].dying != 0) { + continue; + } + if (this->units[DAT_CurrentUnitSlotID::instance].unknownTestAgainst0_2 != 0) { + continue; + } + if (this->units[DAT_CurrentUnitSlotID::instance].state.generic + == OpenSHC::Map::Units::States::US_JESTER_ROAM_TO) { + continue; + } + if (DAT_MinimapViewState::instance.field15_0x3c == 0) { + if (this->units[DAT_CurrentUnitSlotID::instance].drawX == 0 + && this->units[DAT_CurrentUnitSlotID::instance].drawY == 0) { + continue; + } + if (this->units[DAT_CurrentUnitSlotID::instance].drawX + + this->units[DAT_CurrentUnitSlotID::instance].drawXOffset + >= _hitboxXEnd) { + continue; + } + if (this->units[DAT_CurrentUnitSlotID::instance].drawY + + this->units[DAT_CurrentUnitSlotID::instance].someDrawYOffset + >= _hitboxYEnd) { + continue; + } + if (this->units[DAT_CurrentUnitSlotID::instance].spriteWidthUnk + + this->units[DAT_CurrentUnitSlotID::instance].drawX + + this->units[DAT_CurrentUnitSlotID::instance].drawXOffset + < _hitboxXStart) { + continue; + } + if (this->units[DAT_CurrentUnitSlotID::instance].spriteHeightUnk + + this->units[DAT_CurrentUnitSlotID::instance].drawY + + this->units[DAT_CurrentUnitSlotID::instance].someDrawYOffset + < _hitboxYStart) { + continue; + } + } else { + int _tileDistanceX = DAT_ViewportRenderState::instance.viewportState.mouseTileX + - this->units[DAT_CurrentUnitSlotID::instance].x; + if (_tileDistanceX < 0) { + _tileDistanceX = -_tileDistanceX; + } + if (_tileDistanceX > 1) { + continue; + } + int _tileDistanceY = DAT_ViewportRenderState::instance.viewportState.mouseTileY + - this->units[DAT_CurrentUnitSlotID::instance].y; + if (_tileDistanceY < 0) { + _tileDistanceY = -_tileDistanceY; + } + if (_tileDistanceY > 1) { + continue; + } + } + if (this->units[DAT_CurrentUnitSlotID::instance].unitType == OpenSHC::Map::Units::UT_S_TOWER + && this->units[DAT_CurrentUnitSlotID::instance].state.generic + == (OpenSHC::Map::Units::States::US_STAND_UPUnk | OpenSHC::Map::Units::States::US_IDLEUnk)) { + continue; + } + if (this->units[DAT_CurrentUnitSlotID::instance].unitType == OpenSHC::Map::Units::UT_TUNNELER + && (this->units[DAT_CurrentUnitSlotID::instance].state.generic + == OpenSHC::Map::Units::States::US_LOOK_AROUNDUnk + || this->units[DAT_CurrentUnitSlotID::instance].state.generic + == OpenSHC::Map::Units::States::US_STAND_UPUnk)) { + continue; + } + if (this->units[DAT_CurrentUnitSlotID::instance].unitType == OpenSHC::Map::Units::UT_CAMELSHBEAR) { + continue; + } + if (this->units[DAT_CurrentUnitSlotID::instance].unitType == OpenSHC::Map::Units::UT_ANTELOPESHDEER + && MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::selectionHasNoRangedUnits, this)() + != 0) { + continue; + } + switch (param_1) { + case 0: + return DAT_CurrentUnitSlotID::instance; + case 1: + if (DAT_GameState::instance.mapAndTime + .playerTeams[this->units[DAT_CurrentUnitSlotID::instance].owner] + != DAT_GameState::instance.mapAndTime.playerTeams[_currentPlayerSlotID]) { + return DAT_CurrentUnitSlotID::instance; + } + break; + case 2: + if (this->units[DAT_CurrentUnitSlotID::instance].owner == _currentPlayerSlotID) { + if (this->units[DAT_CurrentUnitSlotID::instance].unitType == OpenSHC::Map::Units::UT_S_CATAPULT + || this->units[DAT_CurrentUnitSlotID::instance].unitType + == OpenSHC::Map::Units::UT_S_TREBUCHET + || this->units[DAT_CurrentUnitSlotID::instance].unitType + == OpenSHC::Map::Units::UT_S_BATTERINGRAM + || this->units[DAT_CurrentUnitSlotID::instance].unitType == OpenSHC::Map::Units::UT_S_TOWER + || this->units[DAT_CurrentUnitSlotID::instance].unitType + == OpenSHC::Map::Units::UT_S_MANGONEL + || this->units[DAT_CurrentUnitSlotID::instance].unitType + == OpenSHC::Map::Units::UT_S_BALLISTA + || this->units[DAT_CurrentUnitSlotID::instance].unitType + == OpenSHC::Map::Units::UT_S_FBALLISTA + || this->units[DAT_CurrentUnitSlotID::instance].unitType + == OpenSHC::Map::Units::UT_S_SHIELD) { + return DAT_CurrentUnitSlotID::instance; + } + } + break; + case 3: + if (this->units[DAT_CurrentUnitSlotID::instance].owner == _currentPlayerSlotID) { + return DAT_CurrentUnitSlotID::instance; + } + break; + case 4: + if (this->units[DAT_CurrentUnitSlotID::instance].owner != 0 + && this->units[DAT_CurrentUnitSlotID::instance].isSelectable_OR_matchTime != 0) { + return DAT_CurrentUnitSlotID::instance; + } + break; + case 5: + if (this->units[DAT_CurrentUnitSlotID::instance].owner == _currentPlayerSlotID + && this->units[DAT_CurrentUnitSlotID::instance].isSelectable_OR_matchTime != 0) { + return DAT_CurrentUnitSlotID::instance; + } + break; + case 6: + if (this->units[DAT_CurrentUnitSlotID::instance].unitType == OpenSHC::Map::Units::UT_E_LADDER + && this->units[DAT_CurrentUnitSlotID::instance].owner == _currentPlayerSlotID) { + return DAT_CurrentUnitSlotID::instance; + } + } + } + return 0; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 4d4ee9133..41c364fd2 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -60019,7 +60019,7 @@ SHC_3BB0A8C1_0x0053D850 | 69.8% | reg alloc differs SHC_3BB0A8C1_0x0053D900 | 68.8% | orig caches x/y in locals -SHC_3BB0A8C1_0x0053D9C0 | 0.0% | Pending +SHC_3BB0A8C1_0x0053D9C0 | 19.2% | orig shares branch tails SHC_3BB0A8C1_0x0053DC9C | 0.0% | Pending From cd8c881b323a1c1fd70e614136eed690ca15ead2 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:58 +0200 Subject: [PATCH 166/299] reimplement: SHC_3BB0A8C1_0x00535240 35.10% orig walks counter ptr --- .../UnitsState/recountUnitsInSelection.cpp | 161 ++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 162 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/recountUnitsInSelection.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/recountUnitsInSelection.cpp b/src/OpenSHC/Map/Units/UnitsState/recountUnitsInSelection.cpp new file mode 100644 index 000000000..0f8f4c101 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/recountUnitsInSelection.cpp @@ -0,0 +1,161 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Map/Units/UnitLogicState.hpp" + +#include "OpenSHC/Globals/DAT_GameSynchronyState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Map::Units::UnitLogicState; + + // FUNCTION: STRONGHOLDCRUSADER 0x00535240 + void UnitsState::recountUnitsInSelection() + { + this->selectionEuropeanArchers = 0; + this->selectionSpearmen = 0; + this->selectionMacemen = 0; + this->selectionCrossbowmen = 0; + this->selectionPikemen = 0; + this->selectionSwordsmen = 0; + this->selectionKnights = 0; + this->selectionEngineers = 0; + this->selectionLaddermen = 0; + this->selectionTunnelers = 0; + this->selectionMonks = 0; + this->selectionCatapults = 0; + this->selectionTrebuchets = 0; + this->selectionBatteringRam = 0; + this->selectionSiegeTower = 0; + this->selectionShield = 0; + this->selectionMangonel = 0; + this->selectionBallista = 0; + this->nSelectionFireBallistas = 0; + this->selectionArabArcher = 0; + this->selectionArabSlave = 0; + this->selectionArabSlinger = 0; + this->selectionArabAssassin = 0; + this->selectionArabHorseArchers = 0; + this->selectionArabSwordsman = 0; + this->selectionArabFireThrower = 0; + this->selectionFireBallista = 0; + for (int unitID = 1; unitID < (int)this->maxUnitCount; ++unitID) { + if (this->units[unitID].logicalState != OpenSHC::Map::Units::ULS_NORMAL) { + continue; + } + if (this->units[unitID].dying != 0) { + continue; + } + if (this->units[unitID].owner != DAT_GameSynchronyState::instance.currentPlayerSlotID) { + continue; + } + if (this->units[unitID].isSelected == 0) { + continue; + } + switch (this->units[unitID].unitType) { + case OpenSHC::Map::Units::UT_TUNNELER: + this->selectionTunnelers = this->selectionTunnelers + 1; + break; + case OpenSHC::Map::Units::UT_E_ARCHER: + this->selectionEuropeanArchers = this->selectionEuropeanArchers + 1; + break; + case OpenSHC::Map::Units::UT_E_XBOW: + this->selectionCrossbowmen = this->selectionCrossbowmen + 1; + break; + case OpenSHC::Map::Units::UT_E_SPEAR: + this->selectionSpearmen = this->selectionSpearmen + 1; + break; + case OpenSHC::Map::Units::UT_E_PIKE: + this->selectionPikemen = this->selectionPikemen + 1; + break; + case OpenSHC::Map::Units::UT_E_MACE: + this->selectionMacemen = this->selectionMacemen + 1; + break; + case OpenSHC::Map::Units::UT_E_SWORD: + this->selectionSwordsmen = this->selectionSwordsmen + 1; + break; + case OpenSHC::Map::Units::UT_E_KNIGHT: + this->selectionKnights = this->selectionKnights + 1; + break; + case OpenSHC::Map::Units::UT_E_LADDER: + this->selectionLaddermen = this->selectionLaddermen + 1; + break; + case OpenSHC::Map::Units::UT_E_ENGINEER: + this->selectionEngineers = this->selectionEngineers + 1; + break; + case OpenSHC::Map::Units::UT_E_MONK: + this->selectionMonks = this->selectionMonks + 1; + break; + case OpenSHC::Map::Units::UT_S_CATAPULT: + this->selectionCatapults = this->selectionCatapults + 1; + break; + case OpenSHC::Map::Units::UT_S_TREBUCHET: + this->selectionTrebuchets = this->selectionTrebuchets + 1; + break; + case OpenSHC::Map::Units::UT_S_MANGONEL: + this->selectionMangonel = this->selectionMangonel + 1; + break; + case OpenSHC::Map::Units::UT_S_TOWER: + this->selectionSiegeTower = this->selectionSiegeTower + 1; + break; + case OpenSHC::Map::Units::UT_S_BATTERINGRAM: + this->selectionBatteringRam = this->selectionBatteringRam + 1; + break; + case OpenSHC::Map::Units::UT_S_SHIELD: + this->selectionShield = this->selectionShield + 1; + break; + case OpenSHC::Map::Units::UT_S_BALLISTA: + this->selectionBallista = this->selectionBallista + 1; + break; + case OpenSHC::Map::Units::UT_A_ARCHER: + this->selectionArabArcher = this->selectionArabArcher + 1; + break; + case OpenSHC::Map::Units::UT_A_SLAVE: + this->selectionArabSlave = this->selectionArabSlave + 1; + break; + case OpenSHC::Map::Units::UT_A_SLINGER: + this->selectionArabSlinger = this->selectionArabSlinger + 1; + break; + case OpenSHC::Map::Units::UT_A_ASSASSIN: + this->selectionArabAssassin = this->selectionArabAssassin + 1; + break; + case OpenSHC::Map::Units::UT_A_HARCHER: + this->selectionArabHorseArchers = this->selectionArabHorseArchers + 1; + break; + case OpenSHC::Map::Units::UT_A_SWORDSMAN: + this->selectionArabSwordsman = this->selectionArabSwordsman + 1; + break; + case OpenSHC::Map::Units::UT_A_FIRETHROWER: + this->selectionArabFireThrower = this->selectionArabFireThrower + 1; + break; + case OpenSHC::Map::Units::UT_S_FBALLISTA: + this->selectionFireBallista = this->selectionFireBallista + 1; + break; + default: + continue; + } + this->nHasOwnedUnitInSelection = 1; + } + this->selectionSlots[1] = -1; + this->selectionSlots[2] = -1; + this->selectionSlots[3] = -1; + this->selectionSlots[4] = -1; + this->selectionSlots[5] = -1; + this->selectionSlots[6] = -1; + this->selectionSlots[7] = -1; + this->selectionSlots[0] = -1; + int _slot = 0; + for (int i = 0; i < 27; ++i) { + if ((&this->selectionEuropeanArchers)[i] != 0) { + this->selectionSlots[_slot] = i; + _slot = _slot + 1; + if (_slot > 7) { + return; + } + } + } + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 41c364fd2..cc8c4ddcf 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -50863,7 +50863,7 @@ SHC_3BB0A8C1_0x005351C0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00535200 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x00535240 | 0.0% | Pending +SHC_3BB0A8C1_0x00535240 | 35.1% | orig walks counter ptr SHC_3BB0A8C1_0x00535460 | 0.0% | Pending From 36c2be3fdb29de67dcb74883e5747588cd12ecf5 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 03:44:59 +0200 Subject: [PATCH 167/299] reimplement: SHC_3BB0A8C1_0x0052F7E0 17.62% orig caches height locals --- .../UnitsState/calculateUnitMovementSpeed.cpp | 167 ++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 168 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/calculateUnitMovementSpeed.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/calculateUnitMovementSpeed.cpp b/src/OpenSHC/Map/Units/UnitsState/calculateUnitMovementSpeed.cpp new file mode 100644 index 000000000..3e7f3a183 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/calculateUnitMovementSpeed.cpp @@ -0,0 +1,167 @@ +#include "OpenSHC/Map/Units/TroopValueState.func.hpp" +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Map/Units/UnitLogicState.hpp" +#include "OpenSHC/Map/Units/UnitType.hpp" + +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_GameSynchronyState.hpp" +#include "OpenSHC/Globals/DAT_LandscapeState.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_TribesState.hpp" +#include "OpenSHC/Globals/DAT_TroopValueState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Map::Units::UnitLogicState; + using OpenSHC::Map::Units::UnitType; + + // FUNCTION: STRONGHOLDCRUSADER 0x0052F7E0 + void UnitsState::calculateUnitMovementSpeed(int unitID) + { + this->units[unitID].field322_0x440 = this->units[unitID].field322_0x440 + 1; + int _tile = this->units[unitID].tile; + int _buildingID = DAT_TileMapState::instance.BuildingLayer[_tile]; + uint _logicFlags = DAT_TileMapState::instance.LogicLayer[_tile]; + if (this->units[unitID].unknownCountdown_0x402 == 0) { + if (_buildingID == 0 && (_logicFlags & 0x10000500) == 0) { + if ((this->units[unitID].field322_0x440 + unitID & 7) != 0) { + return; + } + } else if ((this->units[unitID].field322_0x440 + unitID & 3) != 0) { + return; + } + } + this->units[unitID].isMatchingSpeed = false; + uint _isInMoat = _logicFlags & 0x20000000; + byte _tileHeight = DAT_TileMapState::instance.HeightLayer[_tile]; + if (DAT_TileMapState::instance.OrganismLayer[_tile] != 0 + && DAT_TileMapState::instance.OrganismLayer[_tile] < 2000) { + DAT_LandscapeState::instance.trees[DAT_TileMapState::instance.OrganismLayer[_tile]].state = 3; + } + if (_isInMoat != 0 && (DAT_TileMapState::instance.MacroLayer[_tile] & 0x3f) == 1) { + _isInMoat = 0; + } + if ((DAT_TileMapState::instance.LogicLayer[_tile] & 0x40000000U) != 0) { + _isInMoat = 1; + } + if ((_logicFlags & 0x800000) != 0) { + this->units[unitID].calculatedMovementSpeed = this->units[unitID].movementSpeed; + } else if (this->units[unitID].terrainOrClimbHeight < (int)(uint)_tileHeight) { + int _heightDifference = (uint)_tileHeight - this->units[unitID].terrainOrClimbHeight; + if (_heightDifference > 0x10) { + this->units[unitID].terrainOrClimbHeight = _tileHeight; + this->units[unitID].calculatedMovementSpeed = this->units[unitID].movementSpeed; + } else if (_heightDifference < 2) { + this->units[unitID].terrainOrClimbHeight = this->units[unitID].terrainOrClimbHeight + 1; + this->units[unitID].calculatedMovementSpeed = this->units[unitID].movementSpeed; + } else if (_heightDifference < 4) { + this->units[unitID].calculatedMovementSpeed = this->units[unitID].movementSpeed + 1; + this->units[unitID].terrainOrClimbHeight = this->units[unitID].terrainOrClimbHeight + 2; + } else if (_heightDifference < 8) { + this->units[unitID].calculatedMovementSpeed = this->units[unitID].movementSpeed + 3; + this->units[unitID].terrainOrClimbHeight = this->units[unitID].terrainOrClimbHeight + 3; + } else if (_heightDifference < 0xc) { + this->units[unitID].calculatedMovementSpeed = this->units[unitID].movementSpeed + 4; + this->units[unitID].terrainOrClimbHeight = this->units[unitID].terrainOrClimbHeight + 4; + this->units[unitID].movementRunUpTime = 8; + } else { + this->units[unitID].calculatedMovementSpeed = this->units[unitID].movementSpeed + 5; + this->units[unitID].terrainOrClimbHeight = this->units[unitID].terrainOrClimbHeight + 4; + this->units[unitID].movementRunUpTime = 0xc; + } + } else if ((int)(uint)_tileHeight < this->units[unitID].terrainOrClimbHeight) { + int _heightDifference = this->units[unitID].terrainOrClimbHeight - (uint)_tileHeight; + if (_heightDifference > 0x10) { + this->units[unitID].terrainOrClimbHeight = _tileHeight; + this->units[unitID].calculatedMovementSpeed = this->units[unitID].movementSpeed; + } else if (_heightDifference < 4) { + this->units[unitID].terrainOrClimbHeight = this->units[unitID].terrainOrClimbHeight - 1; + } else if (_heightDifference < 8) { + this->units[unitID].terrainOrClimbHeight = this->units[unitID].terrainOrClimbHeight - 2; + this->units[unitID].calculatedMovementSpeed = this->units[unitID].movementSpeed; + } else if (_heightDifference < 0xc) { + this->units[unitID].terrainOrClimbHeight = this->units[unitID].terrainOrClimbHeight - 3; + this->units[unitID].calculatedMovementSpeed = this->units[unitID].movementSpeed; + } else { + this->units[unitID].terrainOrClimbHeight = this->units[unitID].terrainOrClimbHeight - 4; + this->units[unitID].calculatedMovementSpeed = this->units[unitID].movementSpeed; + } + } else if (this->units[unitID].isSelectable_OR_matchTime == 0) { + this->units[unitID].calculatedMovementSpeed = this->units[unitID].movementSpeed; + } else { + this->units[unitID].calculatedMovementSpeed = this->units[unitID].movementSpeed; + if (this->units[unitID].tribeID > 0 + && DAT_TribesState::instance.tribes[this->units[unitID].tribeID].unitType == (UnitType)0 + && DAT_TribesState::instance.tribes[this->units[unitID].tribeID].freeUnitSpeeds == 0) { + this->units[unitID].calculatedMovementSpeed + = DAT_TribesState::instance.tribes[this->units[unitID].tribeID].movementSpeed; + if (this->units[unitID].calculatedMovementSpeed < this->units[unitID].movementSpeed) { + this->units[unitID].calculatedMovementSpeed = this->units[unitID].movementSpeed; + } + this->units[unitID].isMatchingSpeed = true; + } + } + if (_isInMoat == 0) { + if ((_logicFlags & 0x200000) != 0) { + if ((char)this->units[unitID].negativeHeight < '\x10') { + this->units[unitID].negativeHeight = this->units[unitID].negativeHeight + 4; + } + this->units[unitID].calculatedMovementSpeed = this->units[unitID].calculatedMovementSpeed + 2; + } else if (this->units[unitID].negativeHeight != 0) { + this->units[unitID].negativeHeight = this->units[unitID].negativeHeight - 8; + if ((char)this->units[unitID].negativeHeight < '\0') { + this->units[unitID].negativeHeight = 0; + } + this->units[unitID].calculatedMovementSpeed = this->units[unitID].calculatedMovementSpeed + 3; + } + } else { + if ((char)this->units[unitID].negativeHeight < '\x18') { + this->units[unitID].negativeHeight = this->units[unitID].negativeHeight + 4; + } + if ((char)this->units[unitID].negativeHeight <= '\x04') { + this->units[unitID].calculatedMovementSpeed = this->units[unitID].calculatedMovementSpeed + 3; + } else if ((char)this->units[unitID].negativeHeight < '\n') { + this->units[unitID].calculatedMovementSpeed = this->units[unitID].calculatedMovementSpeed + 4; + } else { + this->units[unitID].calculatedMovementSpeed = this->units[unitID].calculatedMovementSpeed + 6; + } + } + this->units[unitID].field289_0x3ff = 0; + if ((DAT_TileMapState::instance.LogicLayer[_tile] & 8) != 0) { + MACRO_CALL_MEMBER(OpenSHC::Map::Units::TroopValueState_Func::registerSpottedEnemyTile, + DAT_TroopValueState::ptr)(_tile); + } + if (_buildingID == 0) { + return; + } + if ((short)DAT_BuildingsState::instance.buildings[_buildingID].buildingType <= 0x28) { + return; + } + if ((short)DAT_BuildingsState::instance.buildings[_buildingID].buildingType >= 0x2d) { + return; + } + this->units[unitID].field289_0x3ff = 1; + if (DAT_BuildingsState::instance.buildings[_buildingID].owner == this->units[unitID].owner) { + return; + } + if (this->units[unitID].dying != 0) { + return; + } + if (this->units[unitID].logicalState != OpenSHC::Map::Units::ULS_NORMAL) { + return; + } + if (this->units[unitID].owner == 0) { + return; + } + if (DAT_GameSynchronyState::instance.currentPlayerFullIDArray[this->units[unitID].owner] != -1) { + return; + } + DAT_TroopValueState::instance.attackInfo.field128058_0x469dc + = DAT_TroopValueState::instance.attackInfo.field128058_0x469dc + 1; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index cc8c4ddcf..99c55a265 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -49343,7 +49343,7 @@ SHC_3BB0A8C1_0x0052F6C0 | 0.0% | Pending SHC_3BB0A8C1_0x0052F730 | 45.4% | branch shape differs -SHC_3BB0A8C1_0x0052F7E0 | 0.0% | Pending +SHC_3BB0A8C1_0x0052F7E0 | 17.6% | orig caches height locals SHC_3BB0A8C1_0x0052FBB0 | 100.0% | Reimplemented From f1fb68ca0bb2d6875e79611b8c09c77e45e7f5d3 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 09:49:55 +0200 Subject: [PATCH 168/299] reimplement: SHC_3BB0A8C1_0x00532700 9.98% orig caches unit fields --- .../Map/Units/UnitsState/shootProjectile.cpp | 149 ++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 150 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/shootProjectile.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/shootProjectile.cpp b/src/OpenSHC/Map/Units/UnitsState/shootProjectile.cpp new file mode 100644 index 000000000..952aa9a82 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/shootProjectile.cpp @@ -0,0 +1,149 @@ +#include "OpenSHC/Map/Entities/EntityState.func.hpp" +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Map/Entities/EntityType.hpp" +#include "OpenSHC/Map/Units/UnitType.hpp" + +#include "OpenSHC/Globals/DAT_EntityState.hpp" +#include "OpenSHC/Globals/DAT_TribesState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Map::Entities::EntityType; + using OpenSHC::Map::Units::UnitType; + + // FUNCTION: STRONGHOLDCRUSADER 0x00532700 + void UnitsState::shootProjectile( + int unitID, EntityType projectileType, int targetX, int targetY, int targetZUnk) + { + int _offsetX = 0; + int _offsetY = 0; + int _height; + int _targetedUnitID = 0; + if (projectileType == OpenSHC::Map::Entities::ET_TREBUCHET) { + if (this->units[unitID].field243_0x3b0 == 0) { + projectileType = OpenSHC::Map::Entities::ET_TREBUCHET; + } else { + projectileType = OpenSHC::Map::Entities::ET_COW_FLYING; + } + _height = this->units[unitID].buildingHeight + 0x82 + this->units[unitID].terrainOrClimbHeight; + } else if (projectileType == OpenSHC::Map::Entities::ET_CATAPULT) { + switch (this->units[unitID].facingDirection) { + case 0: + _offsetY = -7; + break; + case 1: + _offsetX = 4; + _offsetY = -4; + break; + case 2: + _offsetX = 7; + break; + case 3: + _offsetX = 4; + _offsetY = 4; + break; + case 4: + _offsetY = 7; + break; + case 5: + _offsetX = -4; + _offsetY = 4; + break; + case 6: + _offsetX = -7; + break; + case 7: + _offsetX = -4; + _offsetY = -4; + } + if (this->units[unitID].field243_0x3b0 == 0) { + projectileType = OpenSHC::Map::Entities::ET_CATAPULT; + } else { + projectileType = OpenSHC::Map::Entities::ET_COW_FLYING; + } + _height = this->units[unitID].buildingHeight + 0x38 + this->units[unitID].terrainOrClimbHeight; + } else if (projectileType == OpenSHC::Map::Entities::ET_MANGONEL) { + switch (this->units[unitID].facingDirection) { + case 0: + _offsetY = -2; + break; + case 1: + case 4: + _offsetX = 0; + _offsetY = 0; + break; + case 2: + case 6: + _offsetX = 0; + break; + case 3: + _offsetX = -1; + _offsetY = 1; + break; + case 5: + _offsetX = -2; + _offsetY = 2; + break; + case 7: + _offsetX = 1; + _offsetY = -1; + } + projectileType = OpenSHC::Map::Entities::ET_MANGONEL; + _height = this->units[unitID].buildingHeight + 64 + this->units[unitID].terrainOrClimbHeight; + } else if (projectileType == OpenSHC::Map::Entities::ET_BALLISTA + || projectileType == OpenSHC::Map::Entities::ET_FIREBALLISTA) { + _height = this->units[unitID].buildingHeight + 25 + this->units[unitID].terrainOrClimbHeight; + } else if (projectileType != (EntityType)8 && projectileType != ~OpenSHC::Map::Entities::ET_UNKNOWN) { + _targetedUnitID = this->units[unitID].shootTargetedUnit; + if (this->units[unitID].unitType == OpenSHC::Map::Units::UT_A_HARCHER) { + _height = this->units[unitID].buildingHeight + 45 + this->units[unitID].terrainOrClimbHeight; + } else { + /* This limits the range of arrow type projectiles */ + _height = this->units[unitID].buildingHeight + 30 + this->units[unitID].terrainOrClimbHeight; + } + } else { + switch (this->units[unitID].facingDirection) { + case 0: + _offsetY = -4; + break; + case 1: + _offsetX = 10; + _offsetY = -4; + break; + case 2: + _offsetX = 10; + break; + case 3: + _offsetX = 10; + _offsetY = 4; + break; + case 4: + _offsetY = 4; + break; + case 5: + _offsetY = 4; + _offsetX = -10; + break; + case 6: + _offsetX = -10; + break; + case 7: + _offsetY = -4; + _offsetX = -10; + } + _height = this->units[unitID].buildingHeight + 12 + this->units[unitID].terrainOrClimbHeight; + } + MACRO_CALL_MEMBER(OpenSHC::Map::Entities::EntityState_Func::spawnProjectileEntity, DAT_EntityState::ptr)( + unitID, this->units[unitID].owner, this->units[unitID].calculatedOwnerPlayerIndex, + this->units[unitID].microXPosition + _offsetX, this->units[unitID].microYPosition + _offsetY, _height, + targetX, targetY, targetZUnk, projectileType, _targetedUnitID); + if (this->units[unitID].tribeID != 0) { + DAT_TribesState::instance.tribes[this->units[unitID].tribeID].countdown2 = 500; + } + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 99c55a265..cc8e5d9ea 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -50459,7 +50459,7 @@ SHC_3BB0A8C1_0x005326F1 | 0.0% | Pending SHC_3BB0A8C1_0x005326F2 | 0.0% | Pending -SHC_3BB0A8C1_0x00532700 | 0.0% | Pending +SHC_3BB0A8C1_0x00532700 | 10.0% | orig caches unit fields SHC_3BB0A8C1_0x00532B40 | 0.0% | Pending From a2188b3beb4384735d76b14e1ec72649f36cdd92 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 09:53:26 +0200 Subject: [PATCH 169/299] reimplement: SHC_3BB0A8C1_0x00532700 55.24% orig dups call per branch --- .../Map/Units/UnitsState/shootProjectile.cpp | 86 ++++++++++++++----- status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 64 insertions(+), 24 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/shootProjectile.cpp b/src/OpenSHC/Map/Units/UnitsState/shootProjectile.cpp index 952aa9a82..44c7c663c 100644 --- a/src/OpenSHC/Map/Units/UnitsState/shootProjectile.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/shootProjectile.cpp @@ -5,6 +5,7 @@ #include "OpenSHC/Globals/DAT_EntityState.hpp" #include "OpenSHC/Globals/DAT_TribesState.hpp" +#include "OpenSHC/Globals/DAT_UnitsState.hpp" namespace OpenSHC { namespace Map { @@ -17,18 +18,25 @@ namespace Map { void UnitsState::shootProjectile( int unitID, EntityType projectileType, int targetX, int targetY, int targetZUnk) { - int _offsetX = 0; - int _offsetY = 0; - int _height; - int _targetedUnitID = 0; if (projectileType == OpenSHC::Map::Entities::ET_TREBUCHET) { - if (this->units[unitID].field243_0x3b0 == 0) { - projectileType = OpenSHC::Map::Entities::ET_TREBUCHET; + if (DAT_UnitsState::instance.units[unitID].field243_0x3b0 == 0) { + MACRO_CALL_MEMBER( + OpenSHC::Map::Entities::EntityState_Func::spawnProjectileEntity, DAT_EntityState::ptr)(unitID, + this->units[unitID].owner, this->units[unitID].calculatedOwnerPlayerIndex, + this->units[unitID].microXPosition, this->units[unitID].microYPosition, + this->units[unitID].buildingHeight + 0x82 + this->units[unitID].terrainOrClimbHeight, targetX, + targetY, targetZUnk, OpenSHC::Map::Entities::ET_TREBUCHET, 0); } else { - projectileType = OpenSHC::Map::Entities::ET_COW_FLYING; + MACRO_CALL_MEMBER( + OpenSHC::Map::Entities::EntityState_Func::spawnProjectileEntity, DAT_EntityState::ptr)(unitID, + this->units[unitID].owner, this->units[unitID].calculatedOwnerPlayerIndex, + this->units[unitID].microXPosition, this->units[unitID].microYPosition, + this->units[unitID].buildingHeight + 0x82 + this->units[unitID].terrainOrClimbHeight, targetX, + targetY, targetZUnk, OpenSHC::Map::Entities::ET_COW_FLYING, 0); } - _height = this->units[unitID].buildingHeight + 0x82 + this->units[unitID].terrainOrClimbHeight; } else if (projectileType == OpenSHC::Map::Entities::ET_CATAPULT) { + int _offsetX = 0; + int _offsetY = 0; switch (this->units[unitID].facingDirection) { case 0: _offsetY = -7; @@ -58,13 +66,24 @@ namespace Map { _offsetX = -4; _offsetY = -4; } - if (this->units[unitID].field243_0x3b0 == 0) { - projectileType = OpenSHC::Map::Entities::ET_CATAPULT; + if (DAT_UnitsState::instance.units[unitID].field243_0x3b0 == 0) { + MACRO_CALL_MEMBER( + OpenSHC::Map::Entities::EntityState_Func::spawnProjectileEntity, DAT_EntityState::ptr)(unitID, + this->units[unitID].owner, this->units[unitID].calculatedOwnerPlayerIndex, + this->units[unitID].microXPosition + _offsetX, this->units[unitID].microYPosition + _offsetY, + this->units[unitID].buildingHeight + 0x38 + this->units[unitID].terrainOrClimbHeight, targetX, + targetY, targetZUnk, OpenSHC::Map::Entities::ET_CATAPULT, 0); } else { - projectileType = OpenSHC::Map::Entities::ET_COW_FLYING; + MACRO_CALL_MEMBER( + OpenSHC::Map::Entities::EntityState_Func::spawnProjectileEntity, DAT_EntityState::ptr)(unitID, + this->units[unitID].owner, this->units[unitID].calculatedOwnerPlayerIndex, + this->units[unitID].microXPosition + _offsetX, this->units[unitID].microYPosition + _offsetY, + this->units[unitID].buildingHeight + 0x38 + this->units[unitID].terrainOrClimbHeight, targetX, + targetY, targetZUnk, OpenSHC::Map::Entities::ET_COW_FLYING, 0); } - _height = this->units[unitID].buildingHeight + 0x38 + this->units[unitID].terrainOrClimbHeight; } else if (projectileType == OpenSHC::Map::Entities::ET_MANGONEL) { + int _offsetX = 0; + int _offsetY = 0; switch (this->units[unitID].facingDirection) { case 0: _offsetY = -2; @@ -90,20 +109,40 @@ namespace Map { _offsetX = 1; _offsetY = -1; } - projectileType = OpenSHC::Map::Entities::ET_MANGONEL; - _height = this->units[unitID].buildingHeight + 64 + this->units[unitID].terrainOrClimbHeight; + MACRO_CALL_MEMBER( + OpenSHC::Map::Entities::EntityState_Func::spawnProjectileEntity, DAT_EntityState::ptr)(unitID, + this->units[unitID].owner, this->units[unitID].calculatedOwnerPlayerIndex, + this->units[unitID].microXPosition + _offsetX, this->units[unitID].microYPosition + _offsetY, + this->units[unitID].buildingHeight + 64 + this->units[unitID].terrainOrClimbHeight, targetX, + targetY, targetZUnk, OpenSHC::Map::Entities::ET_MANGONEL, 0); } else if (projectileType == OpenSHC::Map::Entities::ET_BALLISTA || projectileType == OpenSHC::Map::Entities::ET_FIREBALLISTA) { - _height = this->units[unitID].buildingHeight + 25 + this->units[unitID].terrainOrClimbHeight; + MACRO_CALL_MEMBER( + OpenSHC::Map::Entities::EntityState_Func::spawnProjectileEntity, DAT_EntityState::ptr)(unitID, + this->units[unitID].owner, this->units[unitID].calculatedOwnerPlayerIndex, + this->units[unitID].microXPosition, this->units[unitID].microYPosition, + this->units[unitID].buildingHeight + 25 + this->units[unitID].terrainOrClimbHeight, targetX, + targetY, targetZUnk, projectileType, 0); } else if (projectileType != (EntityType)8 && projectileType != ~OpenSHC::Map::Entities::ET_UNKNOWN) { - _targetedUnitID = this->units[unitID].shootTargetedUnit; if (this->units[unitID].unitType == OpenSHC::Map::Units::UT_A_HARCHER) { - _height = this->units[unitID].buildingHeight + 45 + this->units[unitID].terrainOrClimbHeight; + MACRO_CALL_MEMBER( + OpenSHC::Map::Entities::EntityState_Func::spawnProjectileEntity, DAT_EntityState::ptr)(unitID, + this->units[unitID].owner, this->units[unitID].calculatedOwnerPlayerIndex, + this->units[unitID].microXPosition, this->units[unitID].microYPosition, + this->units[unitID].buildingHeight + 45 + this->units[unitID].terrainOrClimbHeight, targetX, + targetY, targetZUnk, projectileType, this->units[unitID].shootTargetedUnit); } else { /* This limits the range of arrow type projectiles */ - _height = this->units[unitID].buildingHeight + 30 + this->units[unitID].terrainOrClimbHeight; + MACRO_CALL_MEMBER( + OpenSHC::Map::Entities::EntityState_Func::spawnProjectileEntity, DAT_EntityState::ptr)(unitID, + this->units[unitID].owner, this->units[unitID].calculatedOwnerPlayerIndex, + this->units[unitID].microXPosition, this->units[unitID].microYPosition, + this->units[unitID].buildingHeight + 30 + this->units[unitID].terrainOrClimbHeight, targetX, + targetY, targetZUnk, projectileType, this->units[unitID].shootTargetedUnit); } } else { + int _offsetX = 0; + int _offsetY = 0; switch (this->units[unitID].facingDirection) { case 0: _offsetY = -4; @@ -133,12 +172,13 @@ namespace Map { _offsetY = -4; _offsetX = -10; } - _height = this->units[unitID].buildingHeight + 12 + this->units[unitID].terrainOrClimbHeight; + MACRO_CALL_MEMBER( + OpenSHC::Map::Entities::EntityState_Func::spawnProjectileEntity, DAT_EntityState::ptr)(unitID, + this->units[unitID].owner, this->units[unitID].calculatedOwnerPlayerIndex, + this->units[unitID].microXPosition + _offsetX, this->units[unitID].microYPosition + _offsetY, + this->units[unitID].buildingHeight + 12 + this->units[unitID].terrainOrClimbHeight, targetX, + targetY, targetZUnk, projectileType, 0); } - MACRO_CALL_MEMBER(OpenSHC::Map::Entities::EntityState_Func::spawnProjectileEntity, DAT_EntityState::ptr)( - unitID, this->units[unitID].owner, this->units[unitID].calculatedOwnerPlayerIndex, - this->units[unitID].microXPosition + _offsetX, this->units[unitID].microYPosition + _offsetY, _height, - targetX, targetY, targetZUnk, projectileType, _targetedUnitID); if (this->units[unitID].tribeID != 0) { DAT_TribesState::instance.tribes[this->units[unitID].tribeID].countdown2 = 500; } diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index cc8e5d9ea..efcff704a 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -50459,7 +50459,7 @@ SHC_3BB0A8C1_0x005326F1 | 0.0% | Pending SHC_3BB0A8C1_0x005326F2 | 0.0% | Pending -SHC_3BB0A8C1_0x00532700 | 10.0% | orig caches unit fields +SHC_3BB0A8C1_0x00532700 | 55.2% | orig dups call per branch SHC_3BB0A8C1_0x00532B40 | 0.0% | Pending From fffcf618df9bd0f68224bcc9abae9538d82695e5 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 09:53:45 +0200 Subject: [PATCH 170/299] reimplement: SHC_3BB0A8C1_0x0053CBD0 35.81% orig caches shooter fields --- .../UnitsState/prepareProjectileTarget.cpp | 186 ++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 187 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/prepareProjectileTarget.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/prepareProjectileTarget.cpp b/src/OpenSHC/Map/Units/UnitsState/prepareProjectileTarget.cpp new file mode 100644 index 000000000..a4cdcfe9c --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/prepareProjectileTarget.cpp @@ -0,0 +1,186 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Random/RNG.func.hpp" + +#include "OpenSHC/Globals/SEC_RNG.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + // FUNCTION: STRONGHOLDCRUSADER 0x0053CBD0 + int UnitsState::prepareProjectileTarget(int shooterID, int targetID, int param_3) + { + uint _targetFixedRng = 0; + if (targetID == -1) { + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::setRandomShootLocation, this)(shooterID, + this->units[shooterID].shootTargetMicroX, this->units[shooterID].shootTargetMicroY, + this->units[shooterID].shootTargetZ); + } else { + _targetFixedRng = this->units[targetID].fixedRng; + this->units[shooterID].shootTargetMicroX = this->units[targetID].x * 8 + 4; + this->units[shooterID].shootTargetMicroY = this->units[targetID].y * 8 + 4; + this->units[shooterID].shootTargetZ + = this->units[targetID].buildingHeight + this->units[targetID].terrainOrClimbHeight; + if (this->units[targetID].tunnelerFinishedDigging == 2) { + int _lead = (param_3 * 133) / 100; + short _adjustment; + /* todo:fixme:ucp: this if-else should be improved to also trigger when the + targetID has negative height (walking in pitch or moat) */ + if (this->units[targetID].stateBasedSpeed == 0) { + if (this->units[targetID].calculatedMovementSpeed < 2) { + _adjustment = (short)((_lead + (_lead >> 0x1f & 0xfU)) >> 4); + } else { + _adjustment = (short)(_lead / (this->units[targetID].calculatedMovementSpeed << 4)); + } + } else { + _adjustment = (short)((_lead + (_lead >> 0x1f & 7U)) >> 3); + } + switch (this->units[targetID].facingDirection) { + case 0: + this->units[shooterID].shootTargetMicroY + = this->units[shooterID].shootTargetMicroY - _adjustment; + break; + case 1: + this->units[shooterID].shootTargetMicroY + = this->units[shooterID].shootTargetMicroY - _adjustment; + this->units[shooterID].shootTargetMicroX + = this->units[shooterID].shootTargetMicroX + _adjustment; + break; + case 2: + this->units[shooterID].shootTargetMicroX + = this->units[shooterID].shootTargetMicroX + _adjustment; + break; + case 3: + this->units[shooterID].shootTargetMicroY + = this->units[shooterID].shootTargetMicroY + _adjustment; + this->units[shooterID].shootTargetMicroX + = this->units[shooterID].shootTargetMicroX + _adjustment; + break; + case 4: + this->units[shooterID].shootTargetMicroY + = this->units[shooterID].shootTargetMicroY + _adjustment; + break; + case 5: + this->units[shooterID].shootTargetMicroY + = this->units[shooterID].shootTargetMicroY + _adjustment; + this->units[shooterID].shootTargetMicroX + = this->units[shooterID].shootTargetMicroX - _adjustment; + break; + case 6: + this->units[shooterID].shootTargetMicroX + = this->units[shooterID].shootTargetMicroX - _adjustment; + break; + case 7: + this->units[shooterID].shootTargetMicroY + = this->units[shooterID].shootTargetMicroY - _adjustment; + this->units[shooterID].shootTargetMicroX + = this->units[shooterID].shootTargetMicroX - _adjustment; + } + } + } + int _result = (short)this->units[shooterID].unitType + -0x16; + int _scatter; + if (this->units[shooterID].shootTargetZ < this->units[shooterID].terrainOrClimbHeight) { + switch (this->units[shooterID].unitType) { + case OpenSHC::Map::Units::UT_S_CATAPULT: + case OpenSHC::Map::Units::UT_S_BALLISTA: + _scatter = 0x14; + break; + case OpenSHC::Map::Units::UT_S_TREBUCHET: + _scatter = 0x32; + break; + case OpenSHC::Map::Units::UT_S_MANGONEL: + _scatter = 0x3c; + break; + case OpenSHC::Map::Units::UT_S_FBALLISTA: + _scatter = 10; + break; + default: + return _result; + } + } else { + _scatter = this->units[shooterID].shootTargetZ - this->units[shooterID].terrainOrClimbHeight; + if (_scatter > 0x4b) { + _scatter = _scatter + _scatter / 2; + } + switch (this->units[shooterID].unitType) { + case OpenSHC::Map::Units::UT_S_CATAPULT: + case OpenSHC::Map::Units::UT_S_BALLISTA: + _scatter = _scatter + 0x28; + break; + case OpenSHC::Map::Units::UT_S_TREBUCHET: + _scatter = _scatter + 0x3c; + break; + case OpenSHC::Map::Units::UT_S_MANGONEL: + _scatter = _scatter + 0x46; + break; + case OpenSHC::Map::Units::UT_S_FBALLISTA: + return _result; + } + if (_scatter < 1) { + return _result; + } + if (_scatter > 0x118) { + _scatter = 0x118; + } + } + uint _rng = SEC_RNG::instance.currentNumber2; + MACRO_CALL_MEMBER(OpenSHC::Random::RNG_Func::nextRandomNumber2, SEC_RNG::ptr)(); + _result = ((int)_rng / 300) * 300; + if ((int)_rng % 300 >= _scatter) { + return _result; + } + if ((_rng & 7) < 2) { + _scatter = (_scatter + (_scatter >> 0x1f & 3U)) >> 2; + if (_scatter == 0) { + _scatter = 1; + } + int _horizontalRng + = ((int)(_rng + ((int)_rng >> 0x1f & 0x1ffU)) >> 9) + this->units[shooterID].fixedRng; + if (_horizontalRng < 0) { + _horizontalRng = -_horizontalRng; + } + this->units[shooterID].shootTargetMicroX = this->units[shooterID].shootTargetMicroX + + ((short)(_horizontalRng % _scatter) - (short)(_scatter / 2)); + int _verticalRng = _rng + _targetFixedRng; + if (_verticalRng < 0) { + _verticalRng = -_verticalRng; + } + this->units[shooterID].shootTargetMicroY = this->units[shooterID].shootTargetMicroY + + ((short)(_verticalRng % _scatter) - (short)(_scatter / 2)); + return _verticalRng / _scatter; + } + if ((_rng & 7) < 6) { + _scatter = _scatter / 6; + if (_scatter == 0) { + _scatter = 1; + } + int _heightRng = this->units[shooterID].fixedRng + _rng; + if (_heightRng < 0) { + _heightRng = -_heightRng; + } + int _heightOffset = _heightRng % _scatter + 0x14; + if (_heightRng % _scatter + 0x1c <= (int)this->units[shooterID].shootTargetZ) { + _result = (ushort)this->units[shooterID].shootTargetZ - _heightOffset; + } else { + _result = (ushort)this->units[shooterID].shootTargetZ + _heightOffset; + } + this->units[shooterID].shootTargetZ = (short)_result; + return _result; + } + _scatter = _scatter / 6; + if (_scatter == 0) { + _scatter = 1; + } + int _heightRng = _rng + _targetFixedRng; + if (_heightRng < 0) { + _heightRng = -_heightRng; + } + this->units[shooterID].shootTargetZ + = this->units[shooterID].shootTargetZ + (short)(_heightRng % _scatter) + 0x28; + return _heightRng / _scatter; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index efcff704a..5a69402df 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -59673,7 +59673,7 @@ SHC_3BB0A8C1_0x0053CAC0 | 0.0% | Pending SHC_3BB0A8C1_0x0053CAE0 | 41.7% | loop shape differs -SHC_3BB0A8C1_0x0053CBD0 | 0.0% | Pending +SHC_3BB0A8C1_0x0053CBD0 | 35.8% | orig caches shooter fields SHC_3BB0A8C1_0x0053CF84 | 0.0% | Pending From c780d5f9d365b5378e22056fec0d94ac30cdb19a Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 09:54:08 +0200 Subject: [PATCH 171/299] reimplement: SHC_3BB0A8C1_0x0052E960 83.29% orig walks unit ptr --- .../Map/Units/UnitsState/euroRecruit.cpp | 148 ++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 149 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/euroRecruit.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/euroRecruit.cpp b/src/OpenSHC/Map/Units/UnitsState/euroRecruit.cpp new file mode 100644 index 000000000..5d7dfa042 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/euroRecruit.cpp @@ -0,0 +1,148 @@ +#include "OpenSHC/Game/GameStateStructures.func.hpp" +#include "OpenSHC/Map/Buildings/BuildingsState.func.hpp" +#include "OpenSHC/Map/Units/TribesState.func.hpp" +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Game/GameMode.hpp" +#include "OpenSHC/Game/Resources/ResourceType.hpp" +#include "OpenSHC/Map/Units/States/UnitState.hpp" +#include "OpenSHC/Map/Units/UnitLogicState.hpp" +#include "OpenSHC/Map/Units/UnitType.hpp" + +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_GameState.hpp" +#include "OpenSHC/Globals/DAT_GameSynchronyState.hpp" +#include "OpenSHC/Globals/DAT_TribesState.hpp" +#include "OpenSHC/Globals/DAT_TroopDefinedData.hpp" +#include "OpenSHC/Globals/DAT_UnitPropertiesDefinedData.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Game::GameMode; + using OpenSHC::Game::Resources::ResourceType; + using OpenSHC::Map::Units::UnitLogicState; + using OpenSHC::Map::Units::UnitType; + using OpenSHC::Map::Units::States::UnitState; + + // FUNCTION: STRONGHOLDCRUSADER 0x0052E960 + int UnitsState::euroRecruit(int unitType, undefined4 playersBarracksID, int playerID, int param_4) + { + /* archer is unittype 0x16 */ + this->euroUnitAcquisitionFailReason = 0; + int _unitCost = DAT_TroopDefinedData::instance.MarketResourceCycleArray[unitType + -1]; + int _armourResource + = DAT_UnitPropertiesDefinedData::instance.MELEE_DAMAGE[0x4e][unitType * 4 + 0x49]; + /* fixme: always 0 strange */ + int _unknownResource + = DAT_UnitPropertiesDefinedData::instance.MELEE_DAMAGE[0x4e][unitType * 4 + 0x4a]; + /* bug: if unitType was 0, then it became -0x16, which results in requiring wood + for creating this unit. This is nonsensical. It is wood because it will + access memory DAT_MELEE_DAMAGE_MATRIX[78][72], which happens to be 2 */ + int _weaponResource + = DAT_UnitPropertiesDefinedData::instance.MELEE_DAMAGE[0x4e][unitType * 4 + 0x48]; + int _horseResource = DAT_UnitPropertiesDefinedData::instance.MELEE_DAMAGE[0x4e][unitType * 4 + 0x4b]; + if (DAT_GameSynchronyState::instance.currentGameMode != OpenSHC::Game::GM_SOLITARY + && DAT_GameSynchronyState::instance.skirmishTroopsCostGold == 0) { + _unitCost = 0; + } + if (DAT_GameState::instance.playerDataArray[playerID].currentResources[0xf] < _unitCost) { + this->euroUnitAcquisitionFailReason = 1; + /* if we do not have the gold resources */ + return 0; + } + if (DAT_GameState::instance.playerDataArray[playerID].currentResources[_weaponResource] < 1 + && _weaponResource > 0) { + this->euroUnitAcquisitionFailReason = 2; + this->euroUnitRequiredResource = (ResourceType)_weaponResource; + /* we don't own the weapon required */ + return 0; + } + if (DAT_GameState::instance.playerDataArray[playerID].currentResources[_armourResource] < 1 + && _armourResource > 0) { + this->euroUnitAcquisitionFailReason = 2; + this->euroUnitRequiredResource = (ResourceType)_armourResource; + /* if we do not own the required armor */ + return 0; + } + if (DAT_GameState::instance.playerDataArray[playerID].currentResources[_unknownResource] < 1 + && _unknownResource > 0) { + this->euroUnitAcquisitionFailReason = 2; + this->euroUnitRequiredResource = (ResourceType)_unknownResource; + return 0; + } + if (_horseResource == -1) { + MACRO_CALL_MEMBER( + OpenSHC::Game::GameStateStructures_Func::recountStablesAndHorses, DAT_GameState::ptr)(); + if (DAT_GameState::instance.playerDataArray[playerID].availableHorses < 1) { + this->euroUnitAcquisitionFailReason = 4; + return 0; + } + } + for (int unitID = 1; unitID < (int)this->maxUnitCount; ++unitID) { + if (this->units[unitID].unitType != OpenSHC::Map::Units::UT_PEASANT) { + continue; + } + if (this->units[unitID].owner != playerID) { + continue; + } + if (this->units[unitID].dying != 0) { + continue; + } + if (this->units[unitID].logicalState != OpenSHC::Map::Units::ULS_NORMAL) { + continue; + } + if (this->units[unitID].state.generic == OpenSHC::Map::Units::States::US_RELOAD_WEAPONUnk) { + continue; + } + if (this->units[unitID].state.generic == OpenSHC::Map::Units::States::US_AIM_WEAPONUnk) { + continue; + } + if (this->units[unitID].state.generic == OpenSHC::Map::Units::States::US_JESTER_ROAM_TO) { + continue; + } + if (this->units[unitID].state.generic == OpenSHC::Map::Units::States::US_MELEE_ATTACK) { + continue; + } + if (this->units[unitID].state.generic == OpenSHC::Map::Units::States::US_DETERMINE_NEXT_STATEUnk + && this->units[unitID].isDisappearingUnk != 0) { + continue; + } + if (param_4 != 0) { + return 1; + } + this->units[unitID].unitTypeToChangeInto = (UnitTypeShort)unitType; + this->units[unitID].engineerManningSiegeStateRef_checkType = 1; + this->units[unitID].isDisappearingUnk = 1; + this->units[unitID].state_2 = 0; + this->units[unitID].state.generic = OpenSHC::Map::Units::States::US_JESTER_ROAM_TO; + this->units[unitID].disappearFadeAlphaCountdown = 0; + this->units[unitID].cachedState = OpenSHC::Map::Units::States::US_DETERMINE_NEXT_STATEUnk; + DAT_GameState::instance.playerDataArray[playerID].currentResources[0xf] -= _unitCost; + MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::processResourceLoss, + DAT_BuildingsState::ptr)(playerID, (ResourceType)_weaponResource, 1, 0); + MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::processResourceLoss, + DAT_BuildingsState::ptr)(playerID, (ResourceType)_armourResource, 1, 0); + MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::processResourceLoss, + DAT_BuildingsState::ptr)(playerID, (ResourceType)_unknownResource, 1, 0); + if (_horseResource == -1) { + int _stableBuildingID = MACRO_CALL_MEMBER( + OpenSHC::Game::GameStateStructures_Func::linkageBetweenHorseUnitAndStableUnk, + DAT_GameState::ptr)(playerID, unitID); + this->units[unitID].horseOriginStablesBuildingIndexUnk = (short)_stableBuildingID; + *(int*)&this->units[unitID].horseOriginStableIDUnk + = DAT_BuildingsState::instance.buildings[_stableBuildingID].uid; + } + DAT_GameSynchronyState::instance.finalResults.finalTroopsProduced[playerID] += 1; + MACRO_CALL_MEMBER(OpenSHC::Map::Units::TribesState_Func::aiAssignNewUnitToTribe, DAT_TribesState::ptr)( + playerID, unitType, unitID); + return unitID; + } + this->euroUnitAcquisitionFailReason = 3; + /* units not allowed? over max amount units? */ + return 0; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 5a69402df..0d5d3056b 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -49307,7 +49307,7 @@ SHC_3BB0A8C1_0x0052E7B0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0052E830 | 89.5% | orig walks unit ptr -SHC_3BB0A8C1_0x0052E960 | 0.0% | Pending +SHC_3BB0A8C1_0x0052E960 | 83.3% | orig walks unit ptr SHC_3BB0A8C1_0x0052EC10 | 100.0% | Reimplemented From 6a2e631baa269ad1b0695871e24286beb7de8038 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 09:54:24 +0200 Subject: [PATCH 172/299] reimplement: SHC_3BB0A8C1_0x0053D030 42.88% branch shape differs --- .../UnitsState/harassBuildingsWithSiegeAI.cpp | 191 ++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 192 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/harassBuildingsWithSiegeAI.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/harassBuildingsWithSiegeAI.cpp b/src/OpenSHC/Map/Units/UnitsState/harassBuildingsWithSiegeAI.cpp new file mode 100644 index 000000000..6f81d5961 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/harassBuildingsWithSiegeAI.cpp @@ -0,0 +1,191 @@ +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Synchrony/Actions.func.hpp" +#include "OpenSHC/Synchrony/GameSynchronyState.func.hpp" +#include "OpenSHC/Game/GameMode.hpp" +#include "OpenSHC/Map/Units/Pathfinding/DestinationNeededEnum.hpp" +#include "OpenSHC/Map/Units/States/UnitState.hpp" +#include "OpenSHC/Map/Units/UnitInstructionType.hpp" +#include "OpenSHC/Map/Units/UnitType.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_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 Units { + + using OpenSHC::Game::GameMode; + using OpenSHC::Map::Units::UnitInstructionType; + using OpenSHC::Map::Units::UnitType; + using OpenSHC::Map::Units::Pathfinding::DestinationNeededEnum; + using OpenSHC::Map::Units::States::UnitState; + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x0053D030 + undefined4 UnitsState::harassBuildingsWithSiegeAI(int unitID) + { + int _playerID = this->units[unitID].owner; + int _siegeKind = 0; + int _searchRange = 200; + int _isFireBallista = 0; + switch (this->units[unitID].unitType) { + case OpenSHC::Map::Units::UT_S_CATAPULT: + _siegeKind = 2; + _searchRange = 0x50; + if (this->units[unitID].stoneAmmunition < 1) { + if (DAT_GameSynchronyState::instance.currentGameMode != OpenSHC::Game::GM_SOLITARY + && MACRO_CALL_MEMBER(OpenSHC::Synchrony::GameSynchronyState_Func::isAIPlayer, + DAT_GameSynchronyState::ptr)(_playerID) + != FALSE) { + MACRO_CALL(OpenSHC::Synchrony::Actions_Func::TryAcquireAmmunitionOrPlanToBuyStone)( + _playerID, unitID); + } + return 0; + } + break; + case OpenSHC::Map::Units::UT_S_TREBUCHET: + _siegeKind = 3; + if (this->units[unitID].stoneAmmunition < 1) { + if (DAT_GameSynchronyState::instance.currentGameMode != OpenSHC::Game::GM_SOLITARY + && MACRO_CALL_MEMBER(OpenSHC::Synchrony::GameSynchronyState_Func::isAIPlayer, + DAT_GameSynchronyState::ptr)(_playerID) + != FALSE) { + MACRO_CALL(OpenSHC::Synchrony::Actions_Func::TryAcquireAmmunitionOrPlanToBuyStone)( + _playerID, unitID); + } + return 0; + } + break; + case OpenSHC::Map::Units::UT_S_MANGONEL: + case OpenSHC::Map::Units::UT_S_BALLISTA: + _siegeKind = 4; + break; + case OpenSHC::Map::Units::UT_S_FBALLISTA: + _siegeKind = 0x25; + _isFireBallista = 1; + } + uint _defaultHeightAtTarget = 0; + uint _heightAtTarget = 0; + if (this->units[unitID].field248_0x3bc > 0) { + _defaultHeightAtTarget + = DAT_TileMapState::instance.DefaultHeightLayer[this->units[unitID].field248_0x3bc]; + _heightAtTarget = DAT_TileMapState::instance.HeightLayer[this->units[unitID].field248_0x3bc]; + } + int _shootAtMicroX; + int _shootAtMicroY; + int _shootAtZ; + if (this->units[unitID].targetingType == OpenSHC::Map::Units::UIT_ATTACK_BUILDING) { + if (DAT_BuildingsState::instance.buildings[this->units[unitID].targetID_OR_targetBuildingID].uid + != this->units[unitID] + .targetedUnitUIDUnk_OR_someAppearTileUnk_OR_buildingUID_OR_pitchDitchUID_OR_entityUID) { + this->units[unitID].targetingType = OpenSHC::Map::Units::UIT_NO_INSTRUCTION_OR_MOVEUnk; + return 0; + } + int _halfBuildingSize + = (DAT_BuildingsState::instance.buildings[this->units[unitID].targetID_OR_targetBuildingID] + .widthOrHeight + * 8) + / 2; + _shootAtMicroX = _halfBuildingSize + + (short)DAT_BuildingsState::instance.buildings[this->units[unitID].targetID_OR_targetBuildingID].x + * 8; + _shootAtMicroY = _halfBuildingSize + + (short)DAT_BuildingsState::instance.buildings[this->units[unitID].targetID_OR_targetBuildingID].y + * 8; + _shootAtZ = DAT_BuildingsState::instance.buildings[this->units[unitID].targetID_OR_targetBuildingID] + .terrainHeightUnk; + } else if (this->units[unitID].field248_0x3bc > 0 + && (DAT_TileMapState::instance.LogicLayer[this->units[unitID].field248_0x3bc] & 0x100U) != 0 + && (int)(_heightAtTarget - _defaultHeightAtTarget) >= 0x1f && _siegeKind != 0x25 + && DAT_GameState::instance.mapAndTime.playerTeams[_playerID] + != DAT_GameState::instance.mapAndTime + .playerTeams[(DAT_TileMapState::instance.WallOwnerLayer[this->units[unitID].field248_0x3bc] & 7) + + 1]) { + _shootAtZ = (int)(_heightAtTarget - _defaultHeightAtTarget) / 2 + _defaultHeightAtTarget; + _shootAtMicroX = (this->units[unitID].field248_0x3bc + - DAT_ViewportRenderState::instance + .translationMatrix[DAT_ViewportRenderState::instance + .tileTranslationMatrix_YComponent[this->units[unitID].field248_0x3bc]] + .addXgetTile) + * 8; + _shootAtMicroY = DAT_ViewportRenderState::instance + .tileTranslationMatrix_YComponent[this->units[unitID].field248_0x3bc] + * 8; + } else { + DAT_PathFindingState::instance.ALG_TargetTile = 0; + int _maxTargetDistance = 200; + if (this->units[unitID].aiUnitBehaviourType == 0x15 + || this->units[unitID].unknownSiegeTentRelated02 == 3) { + _maxTargetDistance = 0x14; + } + int _searchFlags; + if (_siegeKind == 0x25) { + _searchFlags = 0x34; + } else if (_siegeKind == 3) { + _searchFlags = 83; + } else { + _searchFlags = 73; + } + int _attackFacingDirection = this->units[unitID].attackFacingDirection; + if (DAT_GameSynchronyState::instance.currentGameMode == OpenSHC::Game::GM_SOLITARY) { + _maxTargetDistance = *(int*)((int)DAT_TroopValueState::instance.attackInfo.scaleValuesArray + + _playerID * 0x177bc + -0x1c) + + 0xf; + } + MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::PathFindingState_Func::findBestAttackTargetTileWithHeightAndOwner, + DAT_PathFindingState::ptr)(_searchFlags, this->units[unitID].x, this->units[unitID].y, + (uint)(ushort)this->units[unitID].facingDirection + _attackFacingDirection & 7, _searchRange, + _attackFacingDirection, this->units[unitID].siegeTargetPlayerID, _maxTargetDistance, + _isFireBallista); + if (DAT_PathFindingState::instance.ALG_TargetTile == 0) { + this->units[unitID].attackFacingDirection = this->units[unitID].attackFacingDirection + '\x01'; + if (this->units[unitID].attackFacingDirection > '\x0f' + && (this->units[unitID].unitType == OpenSHC::Map::Units::UT_S_CATAPULT + || this->units[unitID].unitType == OpenSHC::Map::Units::UT_S_FBALLISTA) + && (this->units[unitID].aiUnitBehaviourType == 0x15 + || DAT_GameSynchronyState::instance.currentGameMode == OpenSHC::Game::GM_SOLITARY + || this->units[unitID].unknownSiegeTentRelated02 == 3)) { + this->units[unitID].state.generic + = (OpenSHC::Map::Units::States::US_STAND_UPUnk | OpenSHC::Map::Units::States::US_IDLEUnk); + this->units[unitID].destinationNeeded + = OpenSHC::Map::Units::Pathfinding::DNE_DESTINATION_NEEDED; + } + } else { + this->units[unitID].facingDirection + = this->units[unitID].facingDirection + (short)this->units[unitID].attackFacingDirection; + this->units[unitID].facingDirection = this->units[unitID].facingDirection & 7; + this->units[unitID].attackFacingDirection = '\0'; + this->units[unitID].shootTargetedUnit = 0; + this->units[unitID].facingDirectionMapOrientationCorrected + = this->units[unitID].facingDirection - (short)DAT_TileMapState::instance.mapOrientation; + if (this->units[unitID].facingDirectionMapOrientationCorrected < 0) { + this->units[unitID].facingDirectionMapOrientationCorrected + = this->units[unitID].facingDirectionMapOrientationCorrected + 8; + } + } + _shootAtMicroX = DAT_PathFindingState::instance.ALG_TargetX * 8; + _shootAtMicroY = DAT_PathFindingState::instance.ALG_TargetY * 8; + _shootAtZ + = DAT_TileMapState::instance.HeightLayer[DAT_PathFindingState::instance.ALG_TargetTile] - 0x2d; + this->units[unitID].field248_0x3bc = DAT_PathFindingState::instance.ALG_TargetTile; + if (DAT_PathFindingState::instance.ALG_TargetTile == 0) { + this->units[unitID].field248_0x3bc = -0x32; + return 0; + } + } + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::setRandomShootLocation, this)( + unitID, _shootAtMicroX, _shootAtMicroY, _shootAtZ); + return 1; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 0d5d3056b..cb4cf4538 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -59923,7 +59923,7 @@ SHC_3BB0A8C1_0x0053D022 | 0.0% | Pending SHC_3BB0A8C1_0x0053D023 | 0.0% | Pending -SHC_3BB0A8C1_0x0053D030 | 0.0% | Pending +SHC_3BB0A8C1_0x0053D030 | 42.9% | branch shape differs SHC_3BB0A8C1_0x0053D388 | 0.0% | Pending From 9e62f40207cc6bd0d651e542cd05bfa2eb5a27d7 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 09:54:37 +0200 Subject: [PATCH 173/299] reimplement: SHC_3BB0A8C1_0x00532BA0 44.40% orig walks unit ptr --- .../recomputeTroopValuesForPlayer.cpp | 157 ++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 158 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/recomputeTroopValuesForPlayer.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/recomputeTroopValuesForPlayer.cpp b/src/OpenSHC/Map/Units/UnitsState/recomputeTroopValuesForPlayer.cpp new file mode 100644 index 000000000..c82c58e2b --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/recomputeTroopValuesForPlayer.cpp @@ -0,0 +1,157 @@ +#include "OpenSHC/IO/LowLevelMemory.func.hpp" +#include "OpenSHC/Map/Navigation/DirectionAlgorithmState.func.hpp" +#include "OpenSHC/Map/Units/TroopValueState.func.hpp" +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Random/RNG.func.hpp" +#include "OpenSHC/Game/GameMode.hpp" +#include "OpenSHC/Map/Units/UnitLogicState.hpp" +#include "OpenSHC/Map/Units/UnitType.hpp" + +#include "OpenSHC/Globals/DAT_DirectionAlgorithmState.hpp" +#include "OpenSHC/Globals/DAT_GameState.hpp" +#include "OpenSHC/Globals/DAT_GameSynchronyState.hpp" +#include "OpenSHC/Globals/DAT_LowLevelMemory.hpp" +#include "OpenSHC/Globals/DAT_TroopValueState.hpp" +#include "OpenSHC/Globals/SEC_RNG.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Game::GameMode; + using OpenSHC::Map::Units::UnitLogicState; + using OpenSHC::Map::Units::UnitType; + + // FUNCTION: STRONGHOLDCRUSADER 0x00532BA0 + void UnitsState::recomputeTroopValuesForPlayer(int playerID) + { + int _campfireY = DAT_GameState::instance.playerDataArray[playerID].campground.yEntry; + int _campfireX = DAT_GameState::instance.playerDataArray[playerID].campground.xEntry; + DAT_GameState::instance.playerDataArray[playerID].enemies = 0; + DAT_GameState::instance.playerDataArray[playerID].totalEnemyUnitsCount = 0; + DAT_GameState::instance.playerDataArray[playerID].sumOfTotalEnemyUnitsCount = 0; + DAT_GameState::instance.playerDataArray[playerID].totalEnemyTroopValueByPlayerID[1] = 0; + DAT_GameState::instance.playerDataArray[playerID].totalEnemyTroopValueByPlayerID[2] = 0; + DAT_GameState::instance.playerDataArray[playerID].totalEnemyTroopValueByPlayerID[3] = 0; + DAT_GameState::instance.playerDataArray[playerID].totalEnemyTroopValueByPlayerID[4] = 0; + DAT_GameState::instance.playerDataArray[playerID].totalEnemyTroopValueByPlayerID[5] = 0; + DAT_GameState::instance.playerDataArray[playerID].totalEnemyTroopValueByPlayerID[6] = 0; + DAT_GameState::instance.playerDataArray[playerID].totalEnemyTroopValueByPlayerID[7] = 0; + DAT_GameState::instance.playerDataArray[playerID].totalEnemyTroopValueByPlayerID[8] = 0; + DAT_GameState::instance.playerDataArray[playerID].totalEnemyTroopValue = 0; + DAT_GameState::instance.playerDataArray[playerID].totalTeamTroopValue = 0; + DAT_GameState::instance.playerDataArray[playerID].totalEnemyRangedTroopValue = 0; + if (DAT_GameSynchronyState::instance.currentGameMode != OpenSHC::Game::GM_SOLITARY && playerID != 0 + && DAT_GameSynchronyState::instance.currentPlayerFullIDArray[playerID] == -1 + && DAT_GameSynchronyState::instance.currentAIArray[playerID] == 0) { + return; + } + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 5000, '\0', DAT_GameState::instance.playerDataArray[playerID].enemyIDArray); + for (int unitID = 1; unitID < (int)this->maxUnitCount; ++unitID) { + if (this->units[unitID].logicalState != OpenSHC::Map::Units::ULS_NORMAL) { + continue; + } + if (this->units[unitID].dying != 0) { + continue; + } + if (this->units[unitID].unknownTestAgainst0_2 != 0) { + continue; + } + if (DAT_GameState::instance.mapAndTime.playerTeams[this->units[unitID].owner] + == DAT_GameState::instance.mapAndTime.playerTeams[playerID]) { + if (this->units[unitID].isSelectable_OR_matchTime == 0) { + continue; + } + MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::DirectionAlgorithmState_Func::setAxisBasedDistanceResult, + DAT_DirectionAlgorithmState::ptr)( + _campfireX, _campfireY, this->units[unitID].x, this->units[unitID].y); + if (DAT_DirectionAlgorithmState::instance.distanceHigh < 60) { + DAT_GameState::instance.playerDataArray[playerID].totalTeamTroopValue + += MACRO_CALL_MEMBER(OpenSHC::Map::Units::TroopValueState_Func::getValueOfTroopType, + DAT_TroopValueState::ptr)((UnitType)(short)this->units[unitID].unitType); + } + continue; + } + /* unit not in our team */ + switch (this->units[unitID].unitType) { + case OpenSHC::Map::Units::UT_TRADER: + case OpenSHC::Map::Units::UT_TRADERHORSE: + case OpenSHC::Map::Units::UT_CAMELSHBEAR: + case OpenSHC::Map::Units::UT_GHOST: + case OpenSHC::Map::Units::UT_MOTHER: + case OpenSHC::Map::Units::UT_CHILD: + continue; + } + if (this->units[unitID].owner == 0) { + continue; + } + switch (this->units[unitID].unitType) { + case OpenSHC::Map::Units::UT_S_CATAPULT: + case OpenSHC::Map::Units::UT_S_TREBUCHET: + case OpenSHC::Map::Units::UT_S_MANGONEL: + case OpenSHC::Map::Units::UT_S_TOWER: + case OpenSHC::Map::Units::UT_S_SHIELD: + case OpenSHC::Map::Units::UT_S_BALLISTA: + case OpenSHC::Map::Units::UT_S_FBALLISTA: + /* count of currently manning engineers */ + if (this->units[unitID].digTileX__OR__countCurrentlyManningEnginers__OR__forCowsRandomBelow300 + == 0) { + continue; + } + } + if (this->units[unitID].isSelectable_OR_matchTime == 0) { + if (this->units[unitID].unitType == OpenSHC::Map::Units::UT_LORD) { + DAT_GameState::instance.playerDataArray[playerID].totalEnemyUnitsCount += 1; + } + } else { + DAT_GameState::instance.playerDataArray[playerID].totalEnemyUnitsCount += 1; + MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::DirectionAlgorithmState_Func::setAxisBasedDistanceResult, + DAT_DirectionAlgorithmState::ptr)( + _campfireX, _campfireY, this->units[unitID].x, this->units[unitID].y); + if (DAT_DirectionAlgorithmState::instance.distanceHigh < 60 + && (DAT_GameSynchronyState::instance.currentPlayerFullIDArray[this->units[unitID].owner] != -1 + || DAT_GameSynchronyState::instance.currentAIArray[this->units[unitID].owner] == 0 + || this->units[unitID].siegeTargetPlayerID == playerID)) { + DAT_GameState::instance.playerDataArray[playerID] + .totalEnemyTroopValueByPlayerID[this->units[unitID].owner] + += MACRO_CALL_MEMBER(OpenSHC::Map::Units::TroopValueState_Func::getValueOfTroopType, + DAT_TroopValueState::ptr)((UnitType)(short)this->units[unitID].unitType); + DAT_GameState::instance.playerDataArray[playerID].totalEnemyTroopValue + += MACRO_CALL_MEMBER(OpenSHC::Map::Units::TroopValueState_Func::getValueOfTroopType, + DAT_TroopValueState::ptr)((UnitType)(short)this->units[unitID].unitType); + if (this->units[unitID].unitType != OpenSHC::Map::Units::UT_E_ARCHER + && this->units[unitID].unitType != OpenSHC::Map::Units::UT_E_XBOW + && this->units[unitID].unitType != OpenSHC::Map::Units::UT_A_ARCHER + && this->units[unitID].unitType != OpenSHC::Map::Units::UT_A_SLINGER + && this->units[unitID].unitType != OpenSHC::Map::Units::UT_A_HARCHER + && this->units[unitID].unitType != OpenSHC::Map::Units::UT_A_FIRETHROWER) { + DAT_GameState::instance.playerDataArray[playerID].totalEnemyRangedTroopValue + += MACRO_CALL_MEMBER(OpenSHC::Map::Units::TroopValueState_Func::getValueOfTroopType, + DAT_TroopValueState::ptr)((UnitType)(short)this->units[unitID].unitType); + } + } + } + int _enemySlot = DAT_GameState::instance.playerDataArray[playerID].enemies; + if (_enemySlot < 2499) { + DAT_GameState::instance.playerDataArray[playerID].enemies = _enemySlot + 1; + } else { + _enemySlot = SEC_RNG::instance.currentNumber2 % 2500; + MACRO_CALL_MEMBER(OpenSHC::Random::RNG_Func::nextRandomNumber2, SEC_RNG::ptr)(); + if (_enemySlot > 2499) { + break; + } + } + DAT_GameState::instance.playerDataArray[playerID].enemyIDArray[_enemySlot] = (short)unitID; + DAT_GameState::instance.mapAndTime.playerEnemenyUnitUIDShortList[playerID][_enemySlot] + = this->units[unitID].uid; + } + DAT_GameState::instance.playerDataArray[playerID].sumOfTotalEnemyUnitsCount + += DAT_GameState::instance.playerDataArray[playerID].totalEnemyUnitsCount; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index cb4cf4538..91592c48d 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -50509,7 +50509,7 @@ SHC_3BB0A8C1_0x00532B98 | 0.0% | Pending SHC_3BB0A8C1_0x00532B9C | 0.0% | Pending -SHC_3BB0A8C1_0x00532BA0 | 0.0% | Pending +SHC_3BB0A8C1_0x00532BA0 | 44.4% | orig walks unit ptr SHC_3BB0A8C1_0x00532F10 | 0.0% | Pending From c9a88e5fbb32f9d71d095ece717dd6f8906223ef Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 09:55:09 +0200 Subject: [PATCH 174/299] reimplement: SHC_3BB0A8C1_0x00536E30 24.74% branch shape differs --- .../Map/Units/UnitsState/giveMoveCommand.cpp | 123 ++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 124 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/giveMoveCommand.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/giveMoveCommand.cpp b/src/OpenSHC/Map/Units/UnitsState/giveMoveCommand.cpp new file mode 100644 index 000000000..32a196229 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/giveMoveCommand.cpp @@ -0,0 +1,123 @@ +#include "OpenSHC/Audio/MSS/SoundSystem.func.hpp" +#include "OpenSHC/Audio/SFX/SFXState.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/Synchrony/GameSynchronyState.func.hpp" +#include "OpenSHC/Commands/GameCommandType.hpp" +#include "OpenSHC/Map/Units/UnitType.hpp" +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +#include "OpenSHC/Globals/DAT_GameSynchronyState.hpp" +#include "OpenSHC/Globals/DAT_PathFindingState.hpp" +#include "OpenSHC/Globals/DAT_SFXState.hpp" +#include "OpenSHC/Globals/DAT_SoundSystemState.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_TribesState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Commands::GameCommandType; + using OpenSHC::Map::Units::UnitType; + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x00536E30 + void UnitsState::giveMoveCommand(int tribeID, int x, int y, int patrol, int matchUnitSpeeds) + { + DAT_GameSynchronyState::instance.DAT_GameCommandParam1 = x; + DAT_GameSynchronyState::instance.DAT_GameCommandParam2 = y; + DAT_GameSynchronyState::instance.DAT_GameCommandParam0 = tribeID; + DAT_GameSynchronyState::instance.DAT_GameCommandParam3 = patrol; + DAT_GameSynchronyState::instance.DAT_GameCommandParam4 = matchUnitSpeeds; + MACRO_CALL_MEMBER(OpenSHC::Synchrony::GameSynchronyState_Func::queueCommand, DAT_GameSynchronyState::ptr)( + OpenSHC::Commands::GCT_UNITS_MOVE); + UnitType _mostFrequentUnitType + = MACRO_CALL_MEMBER(OpenSHC::Map::Units::TribesState_Func::getMajoritySelectedUnitType, + DAT_TribesState::ptr)(tribeID, (int*)0x0); + ushort _areaAtDestination + = DAT_TileMapState::instance + .PathConnectionLayer[DAT_ViewportRenderState::instance.viewportState.field24_0x60]; + uint _logicAtDestination + = DAT_TileMapState::instance.LogicLayer[DAT_ViewportRenderState::instance.viewportState.field24_0x60]; + int _combatUnitID + = MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::selectionContainsCombatUnit, this)(1); + ushort _areaAtUnit = DAT_TileMapState::instance.PathConnectionLayer[this->units[_combatUnitID].tile]; + if ((DAT_TileMapState::instance.LogicLayer[this->units[_combatUnitID].tile] & 0x40000000U) != 0) { + return; + } + bool _canReachDestination + = MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::PathFindingState_Func::calculateCanPlayerUnitsNavigateToAreaFromArea, + DAT_PathFindingState::ptr)(DAT_GameSynchronyState::instance.currentPlayerSlotID, + (short)_areaAtDestination, (short)_areaAtUnit, + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::canAUnitClimb, this)()) + != 0; + if (MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::selectionHasMobileAssaultUnits, this)() != 0) { + if ((_logicAtDestination & 0x10000100) != 0 + || MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::PathFindingState_Func::calculatePathKeepAndWallsGatesNotAllowed, + DAT_PathFindingState::ptr)(this->units[_combatUnitID].x, this->units[_combatUnitID].y, + DAT_ViewportRenderState::instance.viewportState.field24_0x60 + - DAT_ViewportRenderState::instance + .translationMatrix[DAT_ViewportRenderState::instance.tileTranslationMatrix_YComponent + [DAT_ViewportRenderState::instance.viewportState.field24_0x60]] + .addXgetTile, + DAT_ViewportRenderState::instance.tileTranslationMatrix_YComponent + [DAT_ViewportRenderState::instance.viewportState.field24_0x60], + 100000) + == 0) { + _canReachDestination = false; + } + } + if (matchUnitSpeeds == 0 + && (_mostFrequentUnitType == OpenSHC::Map::Units::UT_E_ARCHER + || _mostFrequentUnitType == OpenSHC::Map::Units::UT_E_XBOW + || _mostFrequentUnitType == OpenSHC::Map::Units::UT_S_CATAPULT)) { + return; + } + if (DAT_TribesState::instance.tribes[tribeID].owner + != DAT_GameSynchronyState::instance.currentPlayerSlotID) { + return; + } + if (_mostFrequentUnitType == OpenSHC::Map::Units::UT_S_MANGONEL) { + return; + } + if (_mostFrequentUnitType == OpenSHC::Map::Units::UT_S_BALLISTA) { + return; + } + if (_mostFrequentUnitType == OpenSHC::Map::Units::UT_S_TREBUCHET) { + return; + } + if (!_canReachDestination) { + MACRO_CALL_MEMBER(OpenSHC::Audio::SFX::SFXState_Func::playUnitSpeech, DAT_SFXState::ptr)( + _mostFrequentUnitType, 9); + return; + } + MACRO_CALL_MEMBER(OpenSHC::Map::Units::TribesState_Func::playUnitSelectionSound, DAT_TribesState::ptr)( + tribeID); + if (MACRO_CALL_MEMBER( + OpenSHC::Audio::MSS::SoundSystem_Func::shouldSoundXNotBePlaying, DAT_SoundSystemState::ptr)() + != FALSE) { + return; + } + if (this->units[_combatUnitID].unitType == OpenSHC::Map::Units::UT_E_ENGINEER + && this->units[_combatUnitID].resourceToDeposit != 0) { + return; + } + short _leaderUnitID = DAT_TribesState::instance.tribes[tribeID].selectionTargetUnitID; + if ((this->units[_leaderUnitID].x - x) + 0x48U > 0x90 + || (this->units[_leaderUnitID].y - y) + 0x48U > 0x90) { + MACRO_CALL_MEMBER(OpenSHC::Audio::SFX::SFXState_Func::playUnitSpeech, DAT_SFXState::ptr)( + _mostFrequentUnitType, 10); + return; + } + MACRO_CALL_MEMBER(OpenSHC::Audio::SFX::SFXState_Func::playUnitSpeech, DAT_SFXState::ptr)( + _mostFrequentUnitType, 6); + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 91592c48d..08892620d 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -51217,7 +51217,7 @@ SHC_3BB0A8C1_0x00536DE0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00536E10 | 0.0% | Pending -SHC_3BB0A8C1_0x00536E30 | 0.0% | Pending +SHC_3BB0A8C1_0x00536E30 | 24.7% | branch shape differs SHC_3BB0A8C1_0x00537070 | 86.4% | enum cast, reg alloc From a5aea28e6e7e0924bae3f9b15174dabfc0b13b7f Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 09:55:22 +0200 Subject: [PATCH 175/299] reimplement: SHC_3BB0A8C1_0x00535BC0 47.16% branch shape differs --- .../UnitsState/playerMakeUnitSelection.cpp | 104 ++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 105 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/playerMakeUnitSelection.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/playerMakeUnitSelection.cpp b/src/OpenSHC/Map/Units/UnitsState/playerMakeUnitSelection.cpp new file mode 100644 index 000000000..461b81a97 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/playerMakeUnitSelection.cpp @@ -0,0 +1,104 @@ +#include "OpenSHC/Audio/SFX/SFXState.func.hpp" +#include "OpenSHC/Map/Units/TribesState.func.hpp" +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Audio/SFX/SpeechEffectID.hpp" +#include "OpenSHC/Map/Units/UnitLogicState.hpp" +#include "OpenSHC/Map/Units/UnitType.hpp" +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +#include "OpenSHC/Globals/DAT_CurrentUnitSlotID.hpp" +#include "OpenSHC/Globals/DAT_GameSynchronyState.hpp" +#include "OpenSHC/Globals/DAT_SFXState.hpp" +#include "OpenSHC/Globals/DAT_TribesState.hpp" +#include "OpenSHC/Globals/DAT_UIDragDropDefinedData.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Audio::SFX::SpeechEffectID; + using OpenSHC::Map::Units::UnitLogicState; + using OpenSHC::Map::Units::UnitType; + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x00535BC0 + void UnitsState::playerMakeUnitSelection(int playerID, int tribeID) + { + this->unitCountOfSelection[playerID] = 0; + for (DAT_CurrentUnitSlotID::instance = 1; (int)DAT_CurrentUnitSlotID::instance < (int)this->maxUnitCount; + DAT_CurrentUnitSlotID::instance = DAT_CurrentUnitSlotID::instance + 1) { + if (this->units[DAT_CurrentUnitSlotID::instance].logicalState == OpenSHC::Map::Units::ULS_NORMAL + && this->units[DAT_CurrentUnitSlotID::instance].dying == 0 + && this->units[DAT_CurrentUnitSlotID::instance].owner == playerID + && MACRO_CALL_MEMBER(OpenSHC::Map::Units::TribesState_Func::unitIsSelectedByPlayer, + DAT_TribesState::ptr)(DAT_CurrentUnitSlotID::instance) + != FALSE) { + this->units[DAT_CurrentUnitSlotID::instance].ifSelectedThenPlayerID = (short)playerID; + this->units[DAT_CurrentUnitSlotID::instance].selectionRelatedFlag = 1; + this->unitCountOfSelection[playerID] = this->unitCountOfSelection[playerID] + 1; + } + } + MACRO_CALL_MEMBER(OpenSHC::Map::Units::TribesState_Func::snapshotSelectionTribeAndComputeStance, + DAT_TribesState::ptr)(playerID); + MACRO_CALL_MEMBER(OpenSHC::Map::Units::TribesState_Func::removeSelectedUnitsFromTheirCurrentTribes, + DAT_TribesState::ptr)(playerID); + int _newTribeID = MACRO_CALL_MEMBER( + OpenSHC::Map::Units::TribesState_Func::createPlayerTribe, DAT_TribesState::ptr)(playerID, 1, tribeID); + MACRO_CALL_MEMBER(OpenSHC::Map::Units::TribesState_Func::addUnitsToTribeAndComputeMovementSpeed, + DAT_TribesState::ptr)(playerID, _newTribeID); + MACRO_CALL_MEMBER(OpenSHC::Map::Units::TribesState_Func::importStoredInfoFromSlot0, DAT_TribesState::ptr)( + playerID, _newTribeID); + if (DAT_TribesState::instance.tribes[_newTribeID].owner + != DAT_GameSynchronyState::instance.currentPlayerSlotID) { + DAT_UIDragDropDefinedData::instance.MenuView_TriggerInitial = TRUE; + return; + } + UnitType _unitType = MACRO_CALL_MEMBER(OpenSHC::Map::Units::TribesState_Func::getMajoritySelectedUnitType, + DAT_TribesState::ptr)(_newTribeID, (int*)0x0); + if (_unitType == OpenSHC::Map::Units::UT_S_CATAPULT || _unitType == OpenSHC::Map::Units::UT_S_TOWER + || _unitType == OpenSHC::Map::Units::UT_S_BATTERINGRAM || _unitType == OpenSHC::Map::Units::UT_S_SHIELD + || _unitType == OpenSHC::Map::Units::UT_S_BALLISTA || _unitType == OpenSHC::Map::Units::UT_S_FBALLISTA + || _unitType == OpenSHC::Map::Units::UT_S_TREBUCHET + || _unitType == OpenSHC::Map::Units::UT_S_MANGONEL) { + int _siegeEngineUnitID = DAT_TribesState::instance.tribes[_newTribeID].selectionTargetUnitID; + int _remainingEngineers = MACRO_CALL_MEMBER( + OpenSHC::Map::Units::UnitsState_Func::getRemainingRequiredEngineers, this)(_siegeEngineUnitID); + if (_remainingEngineers > 0) { + if (this->units[_siegeEngineUnitID] + .digTileX__OR__countCurrentlyManningEnginers__OR__forCowsRandomBelow300 + == 0 + || _remainingEngineers > 3) { + MACRO_CALL_MEMBER(OpenSHC::Audio::SFX::SFXState_Func::playUnitSpeechEffect, DAT_SFXState::ptr)( + 0xe); + } else if (_remainingEngineers == 1) { + MACRO_CALL_MEMBER(OpenSHC::Audio::SFX::SFXState_Func::playUnitSpeechEffect, DAT_SFXState::ptr)( + 0xb); + } else if (_remainingEngineers == 2) { + MACRO_CALL_MEMBER(OpenSHC::Audio::SFX::SFXState_Func::playUnitSpeechEffect, DAT_SFXState::ptr)( + 0xc); + } else if (_remainingEngineers == 3) { + MACRO_CALL_MEMBER(OpenSHC::Audio::SFX::SFXState_Func::playUnitSpeechEffect, DAT_SFXState::ptr)( + 0xd); + } + DAT_UIDragDropDefinedData::instance.MenuView_TriggerInitial = TRUE; + return; + } + if (_unitType == OpenSHC::Map::Units::UT_S_CATAPULT + || _unitType == OpenSHC::Map::Units::UT_S_TREBUCHET) { + if ((this->units[_siegeEngineUnitID].unitType == OpenSHC::Map::Units::UT_S_CATAPULT + || this->units[_siegeEngineUnitID].unitType == OpenSHC::Map::Units::UT_S_TREBUCHET) + && this->units[_siegeEngineUnitID].stoneAmmunition < 1) { + MACRO_CALL_MEMBER(OpenSHC::Audio::SFX::SFXState_Func::playSpeechSFX, DAT_SFXState::ptr)( + OpenSHC::Audio::SFX::SEID_RESOURCE_NEED25); + DAT_UIDragDropDefinedData::instance.MenuView_TriggerInitial = TRUE; + return; + } + } + } + MACRO_CALL_MEMBER(OpenSHC::Audio::SFX::SFXState_Func::playUnitSpeech, DAT_SFXState::ptr)(_unitType, 0); + DAT_UIDragDropDefinedData::instance.MenuView_TriggerInitial = TRUE; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 08892620d..d12f89189 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -51101,7 +51101,7 @@ SHC_3BB0A8C1_0x00535A30 | 67.7% | call+reg alloc differs SHC_3BB0A8C1_0x00535B00 | 61.8% | call+reg alloc differs -SHC_3BB0A8C1_0x00535BC0 | 0.0% | Pending +SHC_3BB0A8C1_0x00535BC0 | 47.2% | branch shape differs SHC_3BB0A8C1_0x00535DF0 | 46.1% | call+reg alloc differs From 2127f4e8d88731b1f46ec8b962919514aee7c8d6 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 09:55:33 +0200 Subject: [PATCH 176/299] reimplement: SHC_3BB0A8C1_0x0054C1C0 32.51% branch shape differs --- .../Map/Units/UnitsState/unitClimbing.cpp | 147 ++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 148 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/unitClimbing.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/unitClimbing.cpp b/src/OpenSHC/Map/Units/UnitsState/unitClimbing.cpp new file mode 100644 index 000000000..08cb2b53a --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/unitClimbing.cpp @@ -0,0 +1,147 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Map/Units/States/UnitState.hpp" + +#include "OpenSHC/Globals/DAT_PathFindingState.hpp" +#include "OpenSHC/Globals/DAT_UnitPropertiesDefinedData.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Map::Units::States::UnitState; + + // FUNCTION: STRONGHOLDCRUSADER 0x0054C1C0 + void UnitsState::unitClimbing(int unitID) + { + /* Offsets: + 0x25E(0x364): climbingState (0 to 5, climbing stops at 5) + 0x6CE(0x0BA): groundHeight + 0x70A(0x0F6): currentIndexInPathPlan + 0x8B2(0x29E): unknown + 0x972(0x35E): climbingDirection */ + short _climbDataID = this->units[unitID].climbDataID; + if (DAT_PathFindingState::instance.climbData[_climbDataID].canBeUsed == 0 + || DAT_PathFindingState::instance.climbData[_climbDataID].climbDataRelated + != this->units[unitID].climbDataRelated) { + if (this->units[unitID].usingTeleport == 1) { + int _climbingState = this->units[unitID].climbingState; + this->units[unitID].animationCycleNumber = 0; + this->units[unitID].tunnelerFinishedDigging = 1; + this->units[unitID].usingTeleport = 0; + if ((short)_climbingState < 0) { + this->units[unitID].state.generic = OpenSHC::Map::Units::States::US_DETERMINE_NEXT_STATEUnk; + return; + } + this->units[unitID].dying = 1; + this->units[unitID].state.generic = OpenSHC::Map::Units::States::US_DEATH_02; + return; + } + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::exitLadder, this)(unitID); + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::setDestinationForUnit, this)( + unitID, this->units[unitID].destinationX_2Unk, this->units[unitID].destinationY_2Unk, 0); + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::changeDestinationByLeftover, this)(unitID); + return; + } + if (DAT_PathFindingState::instance.climbData[_climbDataID].type != 1) { + if (DAT_PathFindingState::instance.climbData[_climbDataID].type != 6 + && DAT_PathFindingState::instance.climbData[_climbDataID].type != 5 + && DAT_PathFindingState::instance.climbData[_climbDataID].type != 4 + && DAT_PathFindingState::instance.climbData[_climbDataID].type != 3 + && DAT_PathFindingState::instance.climbData[_climbDataID].type != 7) { + return; + } + if (this->units[unitID].state.generic == (UnitState)0x6c) { + this->units[unitID].dying = 1; + this->units[unitID].state.generic = OpenSHC::Map::Units::States::US_STONE_DEATH_01; + this->units[unitID].animationCycleNumber = 0; + return; + } + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::exitLadder, this)(unitID); + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::setDestinationForUnit, this)( + unitID, this->units[unitID].destinationX_2Unk, this->units[unitID].destinationY_2Unk, 0); + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::changeDestinationByLeftover, this)(unitID); + return; + } + this->units[unitID].field203_0x35c = this->units[unitID].field203_0x35c + 1; + if (this->units[unitID].field203_0x35c > 0x5f) { + *(short*)&this->units[unitID].climbingState = (short)this->units[unitID].climbingState + 1; + this->units[unitID].field203_0x35c = 0; + if (this->units[unitID].climbingDirection == 1) { + /* Climbing up */ + this->units[unitID].terrainOrClimbHeight = this->units[unitID].terrainOrClimbHeight - 0xf; + } else { + /* Climbing down */ + this->units[unitID].terrainOrClimbHeight = this->units[unitID].terrainOrClimbHeight + 0xf; + } + if ((short)(ushort) + * (byte*)(DAT_ViewportRenderState::instance + .translationMatrix[this->units[unitID].mimicCurrentYPosition] + .addXgetTile + + 0x1d32c38 + this->units[unitID].mimicCurrentXPosition) + < this->units[unitID].terrainOrClimbHeight) { + *(undefined2*)&this->units[unitID].climbingState = 5; + } + } + if (this->units[unitID].climbingDirection == 1) { + /* Climbing up */ + if (this->units[unitID].facingDirectionMapOrientationCorrected == 0) { + this->units[unitID].field41_0x5c = (-4 - (short)this->units[unitID].climbingState) * 2; + } else if (this->units[unitID].facingDirectionMapOrientationCorrected == 2) { + this->units[unitID].field41_0x5c = (short)this->units[unitID].climbingState * -2; + } else if (this->units[unitID].facingDirectionMapOrientationCorrected == 4) { + this->units[unitID].field41_0x5c = (short)this->units[unitID].climbingState * 2; + } else if (this->units[unitID].facingDirectionMapOrientationCorrected == 6) { + this->units[unitID].field41_0x5c = (short)this->units[unitID].climbingState * 2 + 8; + } + } else { + /* Climbing down */ + if (this->units[unitID].facingDirectionMapOrientationCorrected == 0) { + this->units[unitID].field41_0x5c = (short)this->units[unitID].climbingState * 2 + -3; + } else if (this->units[unitID].facingDirectionMapOrientationCorrected == 2) { + this->units[unitID].field41_0x5c = (short)this->units[unitID].climbingState * 2 + -8; + } else if (this->units[unitID].facingDirectionMapOrientationCorrected == 4) { + this->units[unitID].field41_0x5c = (-4 - (short)this->units[unitID].climbingState) * 2; + } else if (this->units[unitID].facingDirectionMapOrientationCorrected == 6) { + this->units[unitID].field41_0x5c = (2 - (short)this->units[unitID].climbingState) * 2; + } + } + if (this->units[unitID].climbingDirection == 1) { + /* Climbing up */ + this->units[unitID].animationFrame + = (char)DAT_UnitPropertiesDefinedData::instance.Frames_Shared_UnitClimbingUp + .ANIM_Frames_Shared_UnitClimbingUp[(this->units[unitID].field203_0x35c + + (this->units[unitID].field203_0x35c >> 0x1f & 7U)) + >> 3]; + } else { + /* Climbing down */ + this->units[unitID].animationFrame + = (char)DAT_UnitPropertiesDefinedData::instance + .Frames_Shared_UnitClimbingDown[(this->units[unitID].field203_0x35c + + (this->units[unitID].field203_0x35c >> 0x1f & 7U)) + >> 3]; + } + this->units[unitID].gfxNumber = this->units[unitID].animationSheetFrameOffset + + this->units[unitID].animationFrame * 8 + -8 + + this->units[unitID].facingDirectionMapOrientationCorrected; + this->units[unitID].vanish = 0; + if (this->units[unitID].facingDirectionMapOrientationCorrected == 0 + || this->units[unitID].facingDirectionMapOrientationCorrected == 6) { + this->units[unitID].field43_0x64 = 2; + } else { + this->units[unitID].vanish = 1; + } + /* Stop climbing at climbingState = 5 */ + if ((short)this->units[unitID].climbingState < 5) { + return; + } + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::exitLadder, this)(unitID); + this->units[unitID].state.generic = this->units[unitID].unknownStateCopyClimbRelated; + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::setDestinationForUnit, this)( + unitID, this->units[unitID].destinationX_2Unk, this->units[unitID].destinationY_2Unk, 0); + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::changeDestinationByLeftover, this)(unitID); + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index d12f89189..76f29dd52 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -62503,7 +62503,7 @@ SHC_3BB0A8C1_0x0054BFB3 | 0.0% | Pending SHC_3BB0A8C1_0x0054BFC0 | 46.1% | branch shape differs -SHC_3BB0A8C1_0x0054C1C0 | 0.0% | Pending +SHC_3BB0A8C1_0x0054C1C0 | 32.5% | branch shape differs SHC_3BB0A8C1_0x0054C4F0 | 14.0% | orig walks matrix row ptr From 6775ef6236e16f18d2c286f1f2c92a73dc8f0532 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 09:57:02 +0200 Subject: [PATCH 177/299] reimplement: SHC_3BB0A8C1_0x00539DF0 64.66% hist array via 1st global --- .../Units/UnitsState/chooseHusbandAndWife.cpp | 102 ++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 103 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/chooseHusbandAndWife.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/chooseHusbandAndWife.cpp b/src/OpenSHC/Map/Units/UnitsState/chooseHusbandAndWife.cpp new file mode 100644 index 000000000..c99437414 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/chooseHusbandAndWife.cpp @@ -0,0 +1,102 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Random/RNG.func.hpp" +#include "OpenSHC/Map/Units/UnitLogicState.hpp" +#include "OpenSHC/Map/Units/UnitType.hpp" + +#include "OpenSHC/Globals/DAT_00ee0fe8.hpp" +#include "OpenSHC/Globals/DAT_00ee1028.hpp" +#include "OpenSHC/Globals/DAT_00ee102c.hpp" +#include "OpenSHC/Globals/SEC_RNG.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Map::Units::UnitLogicState; + using OpenSHC::Map::Units::UnitType; + + // FUNCTION: STRONGHOLDCRUSADER 0x00539DF0 + undefined4 UnitsState::chooseHusbandAndWife(int* husbandID, int* wifeID) + { + int _menIDs[100]; + int _womenIDs[100]; + int _menCount = 0; + int _womenCount = 0; + for (int unitID = 1; unitID < (int)this->maxUnitCount; ++unitID) { + if (this->units[unitID].logicalState == OpenSHC::Map::Units::ULS_INVISIBLE) { + continue; + } + if (this->units[unitID].unitType == (UnitType)0) { + continue; + } + if (unitID == DAT_00ee102c::instance || unitID == DAT_00ee1028::instance) { + continue; + } + switch (this->units[unitID].unitType) { + case OpenSHC::Map::Units::UT_WOODCUTTER: + case OpenSHC::Map::Units::UT_FLETCHER: + case OpenSHC::Map::Units::UT_TUNNELER: + case OpenSHC::Map::Units::UT_HUNTER: + case OpenSHC::Map::Units::UT_QUARRYMASON: + case OpenSHC::Map::Units::UT_QUARRYWORKER: + case OpenSHC::Map::Units::UT_PITCHMAN: + case OpenSHC::Map::Units::UT_WHEATFARMER: + case OpenSHC::Map::Units::UT_HOPSFARMER: + case OpenSHC::Map::Units::UT_APPLEFARMER: + case OpenSHC::Map::Units::UT_DAIRYFARMER: + case OpenSHC::Map::Units::UT_MILLER: + case OpenSHC::Map::Units::UT_BAKER: + case OpenSHC::Map::Units::UT_POLETURNER: + case OpenSHC::Map::Units::UT_SMITH: + case OpenSHC::Map::Units::UT_ARMORER: + case OpenSHC::Map::Units::UT_MINER: + case OpenSHC::Map::Units::UT_TRANSPORTMINER: + case OpenSHC::Map::Units::UT_PRIEST: + case OpenSHC::Map::Units::UT_HEALER: + case OpenSHC::Map::Units::UT_DRUNK: + case OpenSHC::Map::Units::UT_INNKEEPER: + case OpenSHC::Map::Units::UT_TRADER: + case OpenSHC::Map::Units::UT_JESTER: + if ((char)this->units[unitID].firstNameIndex < 51 && _menCount < 100) { + _menIDs[_menCount] = unitID; + _menCount = _menCount + 1; + } + break; + case OpenSHC::Map::Units::UT_BREWER: + case OpenSHC::Map::Units::UT_TANNER: + case OpenSHC::Map::Units::UT_MOTHER: + if ((char)this->units[unitID].firstNameIndex > 52 && _womenCount < 100) { + _womenIDs[_womenCount] = unitID; + _womenCount = _womenCount + 1; + } + } + } + if (_womenCount < 1 || _menCount < 1) { + return 0; + } + int _husband = _menIDs[SEC_RNG::instance.currentNumber1 % _menCount]; + MACRO_CALL_MEMBER(OpenSHC::Random::RNG_Func::nextRandomNumber1, SEC_RNG::ptr)(); + int _wife = _womenIDs[SEC_RNG::instance.currentNumber1 % _womenCount]; + MACRO_CALL_MEMBER(OpenSHC::Random::RNG_Func::nextRandomNumber1, SEC_RNG::ptr)(); + /* the eight most recent couples live in the pair array at 0x00EE0FE8 */ + for (int i = 0; i < 8; ++i) { + if (_husband == (&DAT_00ee0fe8::instance)[i * 2] && _wife == (&DAT_00ee0fe8::instance)[i * 2 + 1]) { + return 0; + } + } + *husbandID = _husband; + *wifeID = _wife; + for (int i = 7; i > 0; --i) { + (&DAT_00ee0fe8::instance)[i * 2] = (&DAT_00ee0fe8::instance)[(i - 1) * 2]; + (&DAT_00ee0fe8::instance)[i * 2 + 1] = (&DAT_00ee0fe8::instance)[(i - 1) * 2 + 1]; + } + (&DAT_00ee0fe8::instance)[0] = _husband; + (&DAT_00ee0fe8::instance)[1] = _wife; + DAT_00ee102c::instance = _husband; + DAT_00ee1028::instance = _wife; + return 1; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 76f29dd52..b9c0387a8 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -59295,7 +59295,7 @@ SHC_3BB0A8C1_0x00539DEB | 0.0% | Pending SHC_3BB0A8C1_0x00539DEC | 0.0% | Pending -SHC_3BB0A8C1_0x00539DF0 | 0.0% | Pending +SHC_3BB0A8C1_0x00539DF0 | 64.7% | hist array via 1st global SHC_3BB0A8C1_0x00539FD0 | 0.0% | Pending From 43878e18abcb816b7f0caa23b0970257ef348119 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 10:02:43 +0200 Subject: [PATCH 178/299] reimplement: SHC_3BB0A8C1_0x0053D3D0 13.33% orig dups climb resolve --- .../UnitsState/setDestinationForUnit.cpp | 196 ++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 197 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/setDestinationForUnit.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/setDestinationForUnit.cpp b/src/OpenSHC/Map/Units/UnitsState/setDestinationForUnit.cpp new file mode 100644 index 000000000..e512867cb --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/setDestinationForUnit.cpp @@ -0,0 +1,196 @@ +#include "OpenSHC/IO/LowLevelMemory.func.hpp" +#include "OpenSHC/Map/Navigation/PathFindingState.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_PathFindingState.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_UnitPropertiesDefinedData.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x0053D3D0 + BOOLEnum UnitsState::setDestinationForUnit(int unitID, uint x, uint y, int reusePathingInfo) + { + /* check by unit type */ + int _ableToClimbTowers + = DAT_UnitPropertiesDefinedData::instance.ABLE_TO_CLIMB_TOWERS[(short)this->units[unitID].unitType]; + /* the 400x400 map of placeable tiles at 0x021AEC98 */ + if (x > 399 || y > 399 || *(char*)(y * 400 + 0x21aec98 + x) == '\0') { + DAT_PathFindingState::instance.allAssassinsUnk = 0; + return FALSE; + } + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::teleportUnitToUnitXAndY, this)(unitID); + if (MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::unitIsInMoat, this)(unitID) != FALSE) { + DAT_PathFindingState::instance.climbIsIllegal = 1; + } + this->units[unitID].climbDataID = 0; + this->units[unitID].destinationX_2Unk = (short)x; + this->units[unitID].destinationY_2Unk = (short)y; + this->units[unitID].field280_0x3f4 = 0; + if (this->units[unitID].x == x && this->units[unitID].y == y) { + this->units[unitID].destinationYPosition = (short)y; + this->units[unitID].totalSizeOfPathPlan = 0; + this->units[unitID].tunnelerFinishedDigging = 0; + this->units[unitID].currentIndexInPathPlan = 0; + this->units[unitID].destinationXPosition = (short)x; + this->units[unitID].ladderExitXPosition = this->units[unitID].x; + this->units[unitID].ladderExitYPosition = this->units[unitID].y; + this->units[unitID].destinationTilePosition + = (short)x + DAT_ViewportRenderState::instance.translationMatrix[(short)y].addXgetTile; + this->units[unitID].previousTilePosition + = DAT_ViewportRenderState::instance.translationMatrix[this->units[unitID].y].addXgetTile + + this->units[unitID].x; + DAT_PathFindingState::instance.climbIsIllegal = 0; + DAT_PathFindingState::instance.allAssassinsUnk = 0; + return TRUE; + } + dword _fromArea + = (short)DAT_TileMapState::instance.PathConnectionLayer + [DAT_ViewportRenderState::instance.translationMatrix[this->units[unitID].y].addXgetTile + + this->units[unitID].x]; + int _destinationTile = DAT_ViewportRenderState::instance.translationMatrix[y].addXgetTile + x; + dword _toArea = (short)DAT_TileMapState::instance.PathConnectionLayer[_destinationTile]; + if ((DAT_TileMapState::instance.LogicLayer[_destinationTile] & 0x30) != 0) { + DAT_PathFindingState::instance.allAssassinsUnk = 0; + return FALSE; + } + this->units[unitID].field129_0x2a8 = DAT_TileMapState::instance.PathConnectionLayer[_destinationTile]; + if (_ableToClimbTowers == 0 + && (DAT_TileMapState::instance.LogicLayer[_destinationTile] & 0x10000100U) != 0) { + DAT_PathFindingState::instance.allAssassinsUnk = 0; + return FALSE; + } + uint _pathTargetX = x; + uint _pathTargetY = y; + bool _pathFailed = false; + if (_fromArea != _toArea) { + if (DAT_PathFindingState::instance.climbIsIllegal == 0) { + if (DAT_PathFindingState::instance.allAssassinsUnk == 0 && reusePathingInfo == 0) { + this->units[unitID].field129_0x2a8 + = (short)MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func:: + calculateCanPlayerUnitsNavigateToAreaFromArea, + DAT_PathFindingState::ptr)( + this->units[unitID].owner, _fromArea, _toArea, this->units[unitID].unitCanClimb); + if (this->units[unitID].field129_0x2a8 == 0) { + _pathFailed = true; + } else { + this->units[unitID].climbDataID = (short)MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::PathFindingState_Func::setClimbBasedOnClosestClimbData, + DAT_PathFindingState::ptr)(unitID, _fromArea, this->units[unitID].field129_0x2a8); + if (this->units[unitID].climbDataID == 0) { + _pathFailed = true; + } else { + int _registerResult = MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::PathFindingState_Func::registerUnitOnClimbData, + DAT_PathFindingState::ptr)(this->units[unitID].climbDataID, unitID); + _pathTargetX = DAT_PathFindingState::instance.climbX; + _pathTargetY = DAT_PathFindingState::instance.climbY; + if (_registerResult != 1) { + _pathTargetX = x; + _pathTargetY = y; + if (_registerResult == -1) { + _pathFailed = true; + } + } + } + } + } + } else { + _fromArea = MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::PathFindingState_Func::canNavigateFunctionReturnsArea, + DAT_PathFindingState::ptr)( + this->units[unitID].owner, _toArea, this->units[unitID].x, this->units[unitID].y); + if (_fromArea != _toArea) { + this->units[unitID].field129_0x2a8 + = (short)MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func:: + calculateCanPlayerUnitsNavigateToAreaFromArea, + DAT_PathFindingState::ptr)( + this->units[unitID].owner, _fromArea, _toArea, this->units[unitID].unitCanClimb); + if (this->units[unitID].field129_0x2a8 == 0) { + _pathFailed = true; + } else { + this->units[unitID].climbDataID = (short)MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::PathFindingState_Func::setClimbBasedOnClosestClimbData, + DAT_PathFindingState::ptr)(unitID, _fromArea, this->units[unitID].field129_0x2a8); + if (this->units[unitID].climbDataID == 0) { + _pathFailed = true; + } else { + int _registerResult = MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::PathFindingState_Func::registerUnitOnClimbData, + DAT_PathFindingState::ptr)(this->units[unitID].climbDataID, unitID); + _pathTargetX = DAT_PathFindingState::instance.climbX; + _pathTargetY = DAT_PathFindingState::instance.climbY; + if (_registerResult != 1) { + _pathTargetX = x; + _pathTargetY = y; + if (_registerResult == -1) { + _pathFailed = true; + } + } + } + } + } + } + } + if (!_pathFailed) { + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::copyData, DAT_LowLevelMemory::ptr)( + 1168, &this->units[unitID], this->units); + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 400, '\0', this->units[unitID].pathPlanStart); + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::bindPathPlanToAlgorithmStateAndReset, + DAT_PathFindingState::ptr)(this->units[unitID].pathPlanStart); + DAT_PathFindingState::instance.unitX = this->units[unitID].x; + DAT_PathFindingState::instance.unitY = this->units[unitID].y; + if (this->units[unitID].isSelectable_OR_matchTime == 0) { + DAT_PathFindingState::instance.notAllAssassinsUnk = 1; + } + if (this->units[unitID].field64_0x90 != 0) { + DAT_PathFindingState::instance.notAllAssassinsUnk = 1; + } + DAT_PathFindingState::instance.destinationX = _pathTargetX; + DAT_PathFindingState::instance.destinationY = _pathTargetY; + dword _pathPlanSize; + if (reusePathingInfo == 0) { + _pathPlanSize = MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::doPathfinding, + DAT_PathFindingState::ptr)(this->units[unitID].owner, _ableToClimbTowers); + } else { + _pathPlanSize + = MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::retraceAndCommitPathPlan, + DAT_PathFindingState::ptr)(); + } + DAT_PathFindingState::instance.notAllAssassinsUnk = 0; + if ((int)_pathPlanSize > 0) { + this->units[unitID].totalSizeOfPathPlan = (short)_pathPlanSize; + this->units[unitID].tunnelerFinishedDigging = 2; + this->units[unitID].currentIndexInPathPlan = 0; + this->units[unitID].destinationXPosition = (short)_pathTargetX; + this->units[unitID].destinationYPosition = (short)_pathTargetY; + this->units[unitID].ladderExitYPosition = this->units[unitID].y; + this->units[unitID].destinationTilePosition = (short)_pathTargetX + + DAT_ViewportRenderState::instance.translationMatrix[(short)_pathTargetY].addXgetTile; + this->units[unitID].ladderExitXPosition = this->units[unitID].x; + this->units[unitID].previousTilePosition = this->units[unitID].x + + DAT_ViewportRenderState::instance.translationMatrix[this->units[unitID].y].addXgetTile; + this->units[unitID].cannotClimb = (ushort)(DAT_PathFindingState::instance.climbIsIllegal != 0); + DAT_PathFindingState::instance.climbIsIllegal = 0; + DAT_PathFindingState::instance.allAssassinsUnk = 0; + return TRUE; + } + } + DAT_PathFindingState::instance.climbIsIllegal = 0; + DAT_PathFindingState::instance.allAssassinsUnk = 0; + this->units[unitID].unknownMovementRelated_0x2d2 = 0; + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::despawnUnreachableUnit, this)(unitID); + return FALSE; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index b9c0387a8..1f2228b15 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -60013,7 +60013,7 @@ SHC_3BB0A8C1_0x0053D3C1 | 0.0% | Pending SHC_3BB0A8C1_0x0053D3C2 | 0.0% | Pending -SHC_3BB0A8C1_0x0053D3D0 | 0.0% | Pending +SHC_3BB0A8C1_0x0053D3D0 | 13.3% | orig dups climb resolve SHC_3BB0A8C1_0x0053D850 | 69.8% | reg alloc differs From d635c87f4d7bd0c0618761aff0a2f8b24759f7cd Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 10:03:50 +0200 Subject: [PATCH 179/299] reimplement: SHC_3BB0A8C1_0x0053D3D0 21.48% orig dups climb resolve --- .../UnitsState/setDestinationForUnit.cpp | 193 ++++++++++-------- status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 109 insertions(+), 86 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/setDestinationForUnit.cpp b/src/OpenSHC/Map/Units/UnitsState/setDestinationForUnit.cpp index e512867cb..9ec6f01c2 100644 --- a/src/OpenSHC/Map/Units/UnitsState/setDestinationForUnit.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/setDestinationForUnit.cpp @@ -69,7 +69,6 @@ namespace Map { } uint _pathTargetX = x; uint _pathTargetY = y; - bool _pathFailed = false; if (_fromArea != _toArea) { if (DAT_PathFindingState::instance.climbIsIllegal == 0) { if (DAT_PathFindingState::instance.allAssassinsUnk == 0 && reusePathingInfo == 0) { @@ -79,26 +78,39 @@ namespace Map { DAT_PathFindingState::ptr)( this->units[unitID].owner, _fromArea, _toArea, this->units[unitID].unitCanClimb); if (this->units[unitID].field129_0x2a8 == 0) { - _pathFailed = true; - } else { - this->units[unitID].climbDataID = (short)MACRO_CALL_MEMBER( - OpenSHC::Map::Navigation::PathFindingState_Func::setClimbBasedOnClosestClimbData, - DAT_PathFindingState::ptr)(unitID, _fromArea, this->units[unitID].field129_0x2a8); - if (this->units[unitID].climbDataID == 0) { - _pathFailed = true; - } else { - int _registerResult = MACRO_CALL_MEMBER( - OpenSHC::Map::Navigation::PathFindingState_Func::registerUnitOnClimbData, - DAT_PathFindingState::ptr)(this->units[unitID].climbDataID, unitID); - _pathTargetX = DAT_PathFindingState::instance.climbX; - _pathTargetY = DAT_PathFindingState::instance.climbY; - if (_registerResult != 1) { - _pathTargetX = x; - _pathTargetY = y; - if (_registerResult == -1) { - _pathFailed = true; - } - } + DAT_PathFindingState::instance.climbIsIllegal = 0; + DAT_PathFindingState::instance.allAssassinsUnk = 0; + this->units[unitID].unknownMovementRelated_0x2d2 = 0; + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::despawnUnreachableUnit, this)( + unitID); + return FALSE; + } + this->units[unitID].climbDataID = (short)MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::PathFindingState_Func::setClimbBasedOnClosestClimbData, + DAT_PathFindingState::ptr)(unitID, _fromArea, this->units[unitID].field129_0x2a8); + if (this->units[unitID].climbDataID == 0) { + DAT_PathFindingState::instance.climbIsIllegal = 0; + DAT_PathFindingState::instance.allAssassinsUnk = 0; + this->units[unitID].unknownMovementRelated_0x2d2 = 0; + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::despawnUnreachableUnit, this)( + unitID); + return FALSE; + } + int _registerResult = MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::PathFindingState_Func::registerUnitOnClimbData, + DAT_PathFindingState::ptr)(this->units[unitID].climbDataID, unitID); + _pathTargetX = DAT_PathFindingState::instance.climbX; + _pathTargetY = DAT_PathFindingState::instance.climbY; + if (_registerResult != 1) { + _pathTargetX = x; + _pathTargetY = y; + if (_registerResult == -1) { + DAT_PathFindingState::instance.climbIsIllegal = 0; + DAT_PathFindingState::instance.allAssassinsUnk = 0; + this->units[unitID].unknownMovementRelated_0x2d2 = 0; + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::despawnUnreachableUnit, this)( + unitID); + return FALSE; } } } @@ -114,75 +126,86 @@ namespace Map { DAT_PathFindingState::ptr)( this->units[unitID].owner, _fromArea, _toArea, this->units[unitID].unitCanClimb); if (this->units[unitID].field129_0x2a8 == 0) { - _pathFailed = true; - } else { - this->units[unitID].climbDataID = (short)MACRO_CALL_MEMBER( - OpenSHC::Map::Navigation::PathFindingState_Func::setClimbBasedOnClosestClimbData, - DAT_PathFindingState::ptr)(unitID, _fromArea, this->units[unitID].field129_0x2a8); - if (this->units[unitID].climbDataID == 0) { - _pathFailed = true; - } else { - int _registerResult = MACRO_CALL_MEMBER( - OpenSHC::Map::Navigation::PathFindingState_Func::registerUnitOnClimbData, - DAT_PathFindingState::ptr)(this->units[unitID].climbDataID, unitID); - _pathTargetX = DAT_PathFindingState::instance.climbX; - _pathTargetY = DAT_PathFindingState::instance.climbY; - if (_registerResult != 1) { - _pathTargetX = x; - _pathTargetY = y; - if (_registerResult == -1) { - _pathFailed = true; - } - } + DAT_PathFindingState::instance.climbIsIllegal = 0; + DAT_PathFindingState::instance.allAssassinsUnk = 0; + this->units[unitID].unknownMovementRelated_0x2d2 = 0; + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::despawnUnreachableUnit, this)( + unitID); + return FALSE; + } + this->units[unitID].climbDataID = (short)MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::PathFindingState_Func::setClimbBasedOnClosestClimbData, + DAT_PathFindingState::ptr)(unitID, _fromArea, this->units[unitID].field129_0x2a8); + if (this->units[unitID].climbDataID == 0) { + DAT_PathFindingState::instance.climbIsIllegal = 0; + DAT_PathFindingState::instance.allAssassinsUnk = 0; + this->units[unitID].unknownMovementRelated_0x2d2 = 0; + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::despawnUnreachableUnit, this)( + unitID); + return FALSE; + } + int _registerResult = MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::PathFindingState_Func::registerUnitOnClimbData, + DAT_PathFindingState::ptr)(this->units[unitID].climbDataID, unitID); + _pathTargetX = DAT_PathFindingState::instance.climbX; + _pathTargetY = DAT_PathFindingState::instance.climbY; + if (_registerResult != 1) { + _pathTargetX = x; + _pathTargetY = y; + if (_registerResult == -1) { + DAT_PathFindingState::instance.climbIsIllegal = 0; + DAT_PathFindingState::instance.allAssassinsUnk = 0; + this->units[unitID].unknownMovementRelated_0x2d2 = 0; + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::despawnUnreachableUnit, this)( + unitID); + return FALSE; } } } } } - if (!_pathFailed) { - MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::copyData, DAT_LowLevelMemory::ptr)( - 1168, &this->units[unitID], this->units); - MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( - 400, '\0', this->units[unitID].pathPlanStart); - MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::bindPathPlanToAlgorithmStateAndReset, - DAT_PathFindingState::ptr)(this->units[unitID].pathPlanStart); - DAT_PathFindingState::instance.unitX = this->units[unitID].x; - DAT_PathFindingState::instance.unitY = this->units[unitID].y; - if (this->units[unitID].isSelectable_OR_matchTime == 0) { - DAT_PathFindingState::instance.notAllAssassinsUnk = 1; - } - if (this->units[unitID].field64_0x90 != 0) { - DAT_PathFindingState::instance.notAllAssassinsUnk = 1; - } - DAT_PathFindingState::instance.destinationX = _pathTargetX; - DAT_PathFindingState::instance.destinationY = _pathTargetY; - dword _pathPlanSize; - if (reusePathingInfo == 0) { - _pathPlanSize = MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::doPathfinding, - DAT_PathFindingState::ptr)(this->units[unitID].owner, _ableToClimbTowers); - } else { - _pathPlanSize - = MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::retraceAndCommitPathPlan, - DAT_PathFindingState::ptr)(); - } - DAT_PathFindingState::instance.notAllAssassinsUnk = 0; - if ((int)_pathPlanSize > 0) { - this->units[unitID].totalSizeOfPathPlan = (short)_pathPlanSize; - this->units[unitID].tunnelerFinishedDigging = 2; - this->units[unitID].currentIndexInPathPlan = 0; - this->units[unitID].destinationXPosition = (short)_pathTargetX; - this->units[unitID].destinationYPosition = (short)_pathTargetY; - this->units[unitID].ladderExitYPosition = this->units[unitID].y; - this->units[unitID].destinationTilePosition = (short)_pathTargetX - + DAT_ViewportRenderState::instance.translationMatrix[(short)_pathTargetY].addXgetTile; - this->units[unitID].ladderExitXPosition = this->units[unitID].x; - this->units[unitID].previousTilePosition = this->units[unitID].x - + DAT_ViewportRenderState::instance.translationMatrix[this->units[unitID].y].addXgetTile; - this->units[unitID].cannotClimb = (ushort)(DAT_PathFindingState::instance.climbIsIllegal != 0); - DAT_PathFindingState::instance.climbIsIllegal = 0; - DAT_PathFindingState::instance.allAssassinsUnk = 0; - return TRUE; - } + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::copyData, DAT_LowLevelMemory::ptr)( + 1168, &this->units[unitID], this->units); + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 400, '\0', this->units[unitID].pathPlanStart); + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::bindPathPlanToAlgorithmStateAndReset, + DAT_PathFindingState::ptr)(this->units[unitID].pathPlanStart); + DAT_PathFindingState::instance.unitX = this->units[unitID].x; + DAT_PathFindingState::instance.unitY = this->units[unitID].y; + if (this->units[unitID].isSelectable_OR_matchTime == 0) { + DAT_PathFindingState::instance.notAllAssassinsUnk = 1; + } + if (this->units[unitID].field64_0x90 != 0) { + DAT_PathFindingState::instance.notAllAssassinsUnk = 1; + } + DAT_PathFindingState::instance.destinationX = _pathTargetX; + DAT_PathFindingState::instance.destinationY = _pathTargetY; + dword _pathPlanSize; + if (reusePathingInfo == 0) { + _pathPlanSize = MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::doPathfinding, + DAT_PathFindingState::ptr)(this->units[unitID].owner, _ableToClimbTowers); + } else { + _pathPlanSize + = MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::retraceAndCommitPathPlan, + DAT_PathFindingState::ptr)(); + } + DAT_PathFindingState::instance.notAllAssassinsUnk = 0; + if ((int)_pathPlanSize > 0) { + this->units[unitID].totalSizeOfPathPlan = (short)_pathPlanSize; + this->units[unitID].tunnelerFinishedDigging = 2; + this->units[unitID].currentIndexInPathPlan = 0; + this->units[unitID].destinationXPosition = (short)_pathTargetX; + this->units[unitID].destinationYPosition = (short)_pathTargetY; + this->units[unitID].ladderExitYPosition = this->units[unitID].y; + this->units[unitID].destinationTilePosition = (short)_pathTargetX + + DAT_ViewportRenderState::instance.translationMatrix[(short)_pathTargetY].addXgetTile; + this->units[unitID].ladderExitXPosition = this->units[unitID].x; + this->units[unitID].previousTilePosition = this->units[unitID].x + + DAT_ViewportRenderState::instance.translationMatrix[this->units[unitID].y].addXgetTile; + this->units[unitID].cannotClimb = (ushort)(DAT_PathFindingState::instance.climbIsIllegal != 0); + DAT_PathFindingState::instance.climbIsIllegal = 0; + DAT_PathFindingState::instance.allAssassinsUnk = 0; + return TRUE; } DAT_PathFindingState::instance.climbIsIllegal = 0; DAT_PathFindingState::instance.allAssassinsUnk = 0; diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 1f2228b15..381b08ec7 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -60013,7 +60013,7 @@ SHC_3BB0A8C1_0x0053D3C1 | 0.0% | Pending SHC_3BB0A8C1_0x0053D3C2 | 0.0% | Pending -SHC_3BB0A8C1_0x0053D3D0 | 13.3% | orig dups climb resolve +SHC_3BB0A8C1_0x0053D3D0 | 21.5% | orig dups climb resolve SHC_3BB0A8C1_0x0053D850 | 69.8% | reg alloc differs From 36935ae0174156d525125f51b4b197e84b5034f6 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 10:05:22 +0200 Subject: [PATCH 180/299] reimplement: SHC_3BB0A8C1_0x0053DDD0 65.46% orig unrolls scan loop x4 --- .../selectWorkerSpeechOrMoraleStateID.cpp | 270 ++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 271 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/selectWorkerSpeechOrMoraleStateID.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/selectWorkerSpeechOrMoraleStateID.cpp b/src/OpenSHC/Map/Units/UnitsState/selectWorkerSpeechOrMoraleStateID.cpp new file mode 100644 index 000000000..61aade3e0 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/selectWorkerSpeechOrMoraleStateID.cpp @@ -0,0 +1,270 @@ +#include "OpenSHC/Map/Units.func.hpp" +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Game/GameMode2.hpp" +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +#include "OpenSHC/Globals/DAT_00ee1030.hpp" +#include "OpenSHC/Globals/DAT_00ee1034.hpp" +#include "OpenSHC/Globals/DAT_GameCore.hpp" +#include "OpenSHC/Globals/DAT_GameState.hpp" +#include "OpenSHC/Globals/DAT_GameSynchronyState.hpp" +#include "OpenSHC/Globals/DAT_UnitPropertiesDefinedData.hpp" +#include "OpenSHC/Globals/INT_00ee1038.hpp" +#include "OpenSHC/Globals/SEC_RNG.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Game::GameMode2; + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x0053DDD0 + int UnitsState::selectWorkerSpeechOrMoraleStateID(int unitID) + { + int _blockingState + = MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::getWorkerBlockingStateIfStuck, this)(unitID); + if (_blockingState != 0) { + return _blockingState; + } + uint _rng = this->units[unitID].fixedRng; + uint _rngMod4 = _rng % 4; + if (unitID != INT_00ee1038::instance) { + INT_00ee1038::instance = unitID; + if (DAT_UnitPropertiesDefinedData::instance.field125_0x12260 == 0x19) { + DAT_UnitPropertiesDefinedData::instance.field125_0x12260 = 0; + DAT_UnitPropertiesDefinedData::instance.field126_0x12264 = 0x19; + DAT_UnitPropertiesDefinedData::instance.field127_0x12268 = 10; + } else if (DAT_UnitPropertiesDefinedData::instance.field126_0x12264 == 0x19) { + DAT_UnitPropertiesDefinedData::instance.field125_0x12260 = 10; + DAT_UnitPropertiesDefinedData::instance.field126_0x12264 = 0; + DAT_UnitPropertiesDefinedData::instance.field127_0x12268 = 0x19; + } else if (DAT_UnitPropertiesDefinedData::instance.field127_0x12268 == 0x19) { + DAT_UnitPropertiesDefinedData::instance.field125_0x12260 = 0x19; + DAT_UnitPropertiesDefinedData::instance.field126_0x12264 = 10; + DAT_UnitPropertiesDefinedData::instance.field127_0x12268 = 0; + } + } + int _worstPopularityReason = -1; + int _worstPopularityValue = 0; + for (int i = 0; i < 0x20; ++i) { + if (i <= 4 || (i >= 6 && i <= 10) || i == 0x14 || i >= 0x17) { + continue; + } + if ((&DAT_GameState::instance.mapAndTime.field3092_0x2654)[i] <= 0x27) { + continue; + } + if (_worstPopularityReason == -1 + || (&DAT_GameState::instance.mapAndTime.field3092_0x2654)[i] < _worstPopularityValue) { + _worstPopularityReason = i; + _worstPopularityValue = (&DAT_GameState::instance.mapAndTime.field3092_0x2654)[i]; + } + } + if (_worstPopularityReason != -1) { + if (DAT_UnitPropertiesDefinedData::instance.field124_0x1225c == _worstPopularityReason) { + DAT_00ee1034::instance = DAT_00ee1034::instance + 1; + if (DAT_00ee1034::instance > 1) { + (&DAT_GameState::instance.mapAndTime.field3092_0x2654)[_worstPopularityReason] = 0; + } + } else { + DAT_00ee1034::instance = 0; + DAT_UnitPropertiesDefinedData::instance.field124_0x1225c = _worstPopularityReason; + } + switch (_worstPopularityReason) { + case 5: + return _rngMod4 + 0x74; + case 0xb: + return (MACRO_CALL(OpenSHC::Map::Units_Func::CurrentUnitHasHealer)() != FALSE) + 0x67; + case 0xc: + return 0x79; + case 0xd: + return 0x7a; + case 0xe: + return 0x7c; + case 0xf: + return 0x78; + case 0x10: + return (_rng & 1) + 0x6c; + case 0x11: + return (_rng & 1) + 0x6a; + case 0x12: + return 0x69; + case 0x13: + return 0x7b; + case 0x15: + return _rngMod4 + 0x6e; + case 0x16: + return (_rng & 1) + 0x72; + } + } + int _bestSpeechID = -1; + int _candidateCount = 0; + int _bestWeight = 0; + int _candidateSpeechID = 0; + if (DAT_GameState::instance.playerDataArray[DAT_GameSynchronyState::instance.currentPlayerSlotID] + .totalEnemyUnitsCount + < 10 + || DAT_GameCore::instance.gameMode_2 == OpenSHC::Game::GM_SKIRMISH_AND_MULTIPLAYER + || (DAT_GameCore::instance.gameMode_2 == OpenSHC::Game::GM_CAMPAIGN_MISSION + && DAT_GameCore::instance.missionNumber1to20 > 0xf)) { + DAT_00ee1030::instance = 0; + } else { + DAT_00ee1030::instance = DAT_00ee1030::instance + 1; + _candidateSpeechID = _rngMod4 + 0x62; + _bestWeight = 0x50; + if (DAT_00ee1030::instance > 2) { + _bestWeight = (4 - DAT_00ee1030::instance) * 0x14; + if (_bestWeight < 0x14) { + _bestWeight = 0x14; + } + } + _candidateCount = 100; + _bestSpeechID = _candidateSpeechID; + } + int _weight = 0; + if (DAT_GameState::instance.playerDataArray[DAT_GameSynchronyState::instance.currentPlayerSlotID] + .rationsSetting + == 0) { + _weight = 10; + _candidateSpeechID = _rngMod4 + 0x3c; + } else if (DAT_GameState::instance.playerDataArray[DAT_GameSynchronyState::instance.currentPlayerSlotID] + .rationsSetting + == 1) { + _weight = 0x14; + _candidateSpeechID = _rngMod4 + 0x40; + } else if (DAT_GameState::instance.playerDataArray[DAT_GameSynchronyState::instance.currentPlayerSlotID] + .rationsSetting + == 4) { + _weight = 0x14; + _candidateSpeechID = _rngMod4 + 0x44; + } + if (_weight != 0) { + _candidateCount = _candidateCount + 1; + if (_bestSpeechID == -1 + || _bestWeight < _weight + DAT_UnitPropertiesDefinedData::instance.field125_0x12260) { + _bestWeight = _weight + DAT_UnitPropertiesDefinedData::instance.field125_0x12260; + _bestSpeechID = _candidateSpeechID; + } + } + int _taxesSetting + = DAT_GameState::instance.playerDataArray[DAT_GameSynchronyState::instance.currentPlayerSlotID] + .taxesSetting; + if (_taxesSetting < 4 || _taxesSetting > 7) { + _weight = 0; + if (_taxesSetting == 0) { + _candidateSpeechID = _rngMod4 + 0x49; + _weight = 0x14; + } else if (_taxesSetting == 1) { + _weight = 0xf; + _candidateSpeechID = _rngMod4 + 0x4d; + } else if (_taxesSetting == 2) { + _weight = 10; + _candidateSpeechID = _rngMod4 + 0x51; + } else if (_taxesSetting == 3) { + _weight = 5; + _candidateSpeechID = _rngMod4 + 0x55; + } else if (_taxesSetting == 8) { + _weight = 0xf; + _candidateSpeechID = _rngMod4 + 0x59; + } else if (_taxesSetting == 9 || _taxesSetting == 10 || _taxesSetting == 0xb) { + _candidateSpeechID = _rngMod4 + 0x5d; + _weight = 0x14; + } + if (_weight != 0) { + _candidateCount = _candidateCount + 1; + if (_bestSpeechID == -1 + || _bestWeight < _weight + DAT_UnitPropertiesDefinedData::instance.field126_0x12264) { + _bestWeight = _weight + DAT_UnitPropertiesDefinedData::instance.field126_0x12264; + _bestSpeechID = _candidateSpeechID; + } + } + } + int _productivity + = DAT_GameState::instance.playerDataArray[DAT_GameSynchronyState::instance.currentPlayerSlotID] + .fearFactorProductivityUnk; + _weight = 0; + if (_productivity < 100) { + _candidateCount = _candidateCount + 1; + if (_productivity < 0x3c) { + _weight = 0x19; + _candidateSpeechID = _rngMod4 + 0x12; + } else if (_productivity < 0x46) { + _weight = 0x14; + _candidateSpeechID = _rngMod4 + 0xe; + } else if (_productivity < 0x50) { + _weight = 0xf; + _candidateSpeechID = _rngMod4 + 10; + } else if (_productivity < 0x5a) { + _weight = 10; + _candidateSpeechID = _rngMod4 + 6; + } else { + _weight = 5; + _candidateSpeechID = _rngMod4 + 2; + } + } + if (_productivity >= 0x65) { + _candidateCount = _candidateCount + 1; + if (this->units[unitID].productivityDiv100 == 0 + || MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::isWorkerAtProductionIdleState, this)( + unitID) + == 0) { + if (_productivity < 0x6e) { + _weight = 5; + _candidateSpeechID = _rngMod4 + 0x1b; + } else if (_productivity < 0x78) { + _weight = 10; + _candidateSpeechID = _rngMod4 + 0x1f; + } else if (_productivity < 0x82) { + _weight = 0xf; + _candidateSpeechID = _rngMod4 + 0x23; + } else if (_productivity < 0x8c) { + _weight = 0x14; + _candidateSpeechID = _rngMod4 + 0x27; + } else { + _weight = 0x19; + _candidateSpeechID = _rngMod4 + 0x2b; + } + } else { + switch (this->units[unitID].productivityDiv100) { + case 1: + _weight = 10; + _candidateSpeechID = 0x16; + break; + case 2: + _weight = 0xf; + _candidateSpeechID = 0x17; + break; + case 3: + _weight = 0x14; + _candidateSpeechID = 0x18; + break; + case 4: + _weight = 0x19; + _candidateSpeechID = 0x19; + break; + default: + _weight = 0x19; + _candidateSpeechID = 0x1a; + } + } + } + if (_productivity >= 0x65 || _weight != 0) { + if (_bestSpeechID == -1 + || _bestWeight < DAT_UnitPropertiesDefinedData::instance.field127_0x12268 + _weight) { + _bestSpeechID = _candidateSpeechID; + } + } + if (_candidateCount == 1 && SEC_RNG::instance.currentNumber1 % 3 == 0) { + _bestSpeechID = 1; + } else if (_bestSpeechID == -1) { + return 1; + } + if (_candidateSpeechID < 0x62) { + DAT_00ee1030::instance = 0; + } + return _bestSpeechID; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 381b08ec7..11bde65af 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -60037,7 +60037,7 @@ SHC_3BB0A8C1_0x0053DCB4 | 0.0% | Pending SHC_3BB0A8C1_0x0053DCC0 | 14.9% | orig caches many locals -SHC_3BB0A8C1_0x0053DDD0 | 0.0% | Pending +SHC_3BB0A8C1_0x0053DDD0 | 65.5% | orig unrolls scan loop x4 SHC_3BB0A8C1_0x0053E330 | 0.0% | Pending From 8c4c884cfeba6a17674a3c7cedf379147d5ae92c Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 10:06:41 +0200 Subject: [PATCH 181/299] reimplement: SHC_3BB0A8C1_0x005347E0 61.78% cases 1-8 dead in binary --- .../applyDragBoxSelectionByPriority.cpp | 264 ++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 265 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/applyDragBoxSelectionByPriority.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/applyDragBoxSelectionByPriority.cpp b/src/OpenSHC/Map/Units/UnitsState/applyDragBoxSelectionByPriority.cpp new file mode 100644 index 000000000..e29fcc229 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/applyDragBoxSelectionByPriority.cpp @@ -0,0 +1,264 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Map/Units/States/UnitState.hpp" +#include "OpenSHC/Map/Units/UnitLogicState.hpp" +#include "OpenSHC/Map/Units/UnitType.hpp" + +#include "OpenSHC/Globals/DAT_CurrentUnitSlotID.hpp" +#include "OpenSHC/Globals/DAT_GameSynchronyState.hpp" +#include "OpenSHC/Globals/DAT_MouseState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Map::Units::UnitLogicState; + using OpenSHC::Map::Units::UnitType; + using OpenSHC::Map::Units::States::UnitState; + + // FUNCTION: STRONGHOLDCRUSADER 0x005347E0 + void UnitsState::applyDragBoxSelectionByPriority() + { + this->field14_0x55c = 0; + LONG _boxLeft; + LONG _boxRight; + if (DAT_MouseState::instance.selectionBox.right < DAT_MouseState::instance.selectionBox.left) { + _boxLeft = DAT_MouseState::instance.selectionBox.right; + _boxRight = DAT_MouseState::instance.selectionBox.left; + } else { + _boxLeft = DAT_MouseState::instance.selectionBox.left; + _boxRight = DAT_MouseState::instance.selectionBox.right; + } + LONG _boxTop; + LONG _boxBottom; + if (DAT_MouseState::instance.selectionBox.bottom < DAT_MouseState::instance.selectionBox.top) { + _boxTop = DAT_MouseState::instance.selectionBox.bottom; + _boxBottom = DAT_MouseState::instance.selectionBox.top; + } else { + _boxTop = DAT_MouseState::instance.selectionBox.top; + _boxBottom = DAT_MouseState::instance.selectionBox.bottom; + } + int _otherOwnUnits = 0; + int _catapults = 0; + int _trebuchets = 0; + int _siegeTowers = 0; + int _batteringRams = 0; + int _shields = 0; + int _mangonels = 0; + int _ballistas = 0; + int _priority = 0; + uint _lordUnitID = 0; + int _siegeEngineUnits = 0; + for (DAT_CurrentUnitSlotID::instance = 1; (int)DAT_CurrentUnitSlotID::instance < (int)this->maxUnitCount; + DAT_CurrentUnitSlotID::instance = DAT_CurrentUnitSlotID::instance + 1) { + if (this->units[DAT_CurrentUnitSlotID::instance].logicalState != OpenSHC::Map::Units::ULS_NORMAL + || this->units[DAT_CurrentUnitSlotID::instance].dying != 0 + || this->units[DAT_CurrentUnitSlotID::instance].isSelectable_OR_matchTime == 0 + || this->units[DAT_CurrentUnitSlotID::instance].unknownTestAgainst0_2 != 0 + || this->units[DAT_CurrentUnitSlotID::instance].state.generic + == OpenSHC::Map::Units::States::US_JESTER_ROAM_TO + || (this->units[DAT_CurrentUnitSlotID::instance].drawX == 0 + && this->units[DAT_CurrentUnitSlotID::instance].drawY == 0) + || this->units[DAT_CurrentUnitSlotID::instance].drawX + + this->units[DAT_CurrentUnitSlotID::instance].drawXOffset + >= _boxRight + || this->units[DAT_CurrentUnitSlotID::instance].drawY + + this->units[DAT_CurrentUnitSlotID::instance].someDrawYOffset + >= _boxBottom + || this->units[DAT_CurrentUnitSlotID::instance].spriteWidthUnk + + this->units[DAT_CurrentUnitSlotID::instance].drawX + + this->units[DAT_CurrentUnitSlotID::instance].drawXOffset + < _boxLeft + || this->units[DAT_CurrentUnitSlotID::instance].spriteHeightUnk + + this->units[DAT_CurrentUnitSlotID::instance].drawY + + this->units[DAT_CurrentUnitSlotID::instance].someDrawYOffset + < _boxTop + || (this->units[DAT_CurrentUnitSlotID::instance].unitType == OpenSHC::Map::Units::UT_TUNNELER + && (this->units[DAT_CurrentUnitSlotID::instance].state.generic + == OpenSHC::Map::Units::States::US_LOOK_AROUNDUnk + || this->units[DAT_CurrentUnitSlotID::instance].state.generic + == OpenSHC::Map::Units::States::US_STAND_UPUnk))) { + continue; + } + if (this->units[DAT_CurrentUnitSlotID::instance].owner + != DAT_GameSynchronyState::instance.currentPlayerSlotID) { + if (this->units[DAT_CurrentUnitSlotID::instance].owner != 0) { + this->field14_0x55c = this->units[DAT_CurrentUnitSlotID::instance].owner; + } + continue; + } + if (this->units[DAT_CurrentUnitSlotID::instance].unitType == OpenSHC::Map::Units::UT_LORD) { + _lordUnitID = DAT_CurrentUnitSlotID::instance; + _otherOwnUnits = _otherOwnUnits + 1; + continue; + } + _siegeEngineUnits = _siegeEngineUnits + 1; + if (this->units[DAT_CurrentUnitSlotID::instance].unitType == OpenSHC::Map::Units::UT_S_CATAPULT) { + _catapults = _catapults + 1; + } else if (this->units[DAT_CurrentUnitSlotID::instance].unitType + == OpenSHC::Map::Units::UT_S_TREBUCHET) { + _trebuchets = _trebuchets + 1; + } else if (this->units[DAT_CurrentUnitSlotID::instance].unitType == OpenSHC::Map::Units::UT_S_TOWER) { + _siegeTowers = _siegeTowers + 1; + } else if (this->units[DAT_CurrentUnitSlotID::instance].unitType + == OpenSHC::Map::Units::UT_S_BATTERINGRAM) { + _batteringRams = _batteringRams + 1; + } else if (this->units[DAT_CurrentUnitSlotID::instance].unitType == OpenSHC::Map::Units::UT_S_SHIELD) { + _shields = _shields + 1; + } else if (this->units[DAT_CurrentUnitSlotID::instance].unitType + == OpenSHC::Map::Units::UT_S_MANGONEL) { + _mangonels = _mangonels + 1; + } else if (this->units[DAT_CurrentUnitSlotID::instance].unitType + == OpenSHC::Map::Units::UT_S_BALLISTA) { + _ballistas = _ballistas + 1; + } else if (this->units[DAT_CurrentUnitSlotID::instance].unitType + == OpenSHC::Map::Units::UT_S_FBALLISTA) { + _priority = _priority + 1; + } else { + _otherOwnUnits = _otherOwnUnits + 1; + } + } + if (_lordUnitID != 0 && _siegeEngineUnits != 0) { + _otherOwnUnits = _otherOwnUnits - 1; + _lordUnitID = 0; + } + if (_otherOwnUnits != 0 || _catapults != 0 || _trebuchets != 0 || _siegeTowers != 0 || _batteringRams != 0 + || _shields != 0 || _mangonels != 0 || _ballistas != 0 || _priority != 0) { + _priority = 0; + } else { + _priority = 9; + } + this->totalUnitsInSelection = 0; + for (DAT_CurrentUnitSlotID::instance = 1; (int)DAT_CurrentUnitSlotID::instance < (int)this->maxUnitCount; + DAT_CurrentUnitSlotID::instance = DAT_CurrentUnitSlotID::instance + 1) { + this->units[DAT_CurrentUnitSlotID::instance].isSelected = 0; + if (this->units[DAT_CurrentUnitSlotID::instance].logicalState != OpenSHC::Map::Units::ULS_NORMAL + || this->units[DAT_CurrentUnitSlotID::instance].dying != 0 + || this->units[DAT_CurrentUnitSlotID::instance].isSelectable_OR_matchTime == 0 + || this->units[DAT_CurrentUnitSlotID::instance].unknownTestAgainst0_2 != 0 + || this->units[DAT_CurrentUnitSlotID::instance].state.generic + == OpenSHC::Map::Units::States::US_JESTER_ROAM_TO + || (this->units[DAT_CurrentUnitSlotID::instance].drawX == 0 + && this->units[DAT_CurrentUnitSlotID::instance].drawY == 0) + || this->units[DAT_CurrentUnitSlotID::instance].drawX + + this->units[DAT_CurrentUnitSlotID::instance].drawXOffset + >= _boxRight + || this->units[DAT_CurrentUnitSlotID::instance].drawY + + this->units[DAT_CurrentUnitSlotID::instance].someDrawYOffset + >= _boxBottom + || this->units[DAT_CurrentUnitSlotID::instance].spriteWidthUnk + + this->units[DAT_CurrentUnitSlotID::instance].drawX + + this->units[DAT_CurrentUnitSlotID::instance].drawXOffset + < _boxLeft + || this->units[DAT_CurrentUnitSlotID::instance].spriteHeightUnk + + this->units[DAT_CurrentUnitSlotID::instance].drawY + + this->units[DAT_CurrentUnitSlotID::instance].someDrawYOffset + < _boxTop + || (this->units[DAT_CurrentUnitSlotID::instance].unitType == OpenSHC::Map::Units::UT_TUNNELER + && (this->units[DAT_CurrentUnitSlotID::instance].state.generic + == OpenSHC::Map::Units::States::US_LOOK_AROUNDUnk + || this->units[DAT_CurrentUnitSlotID::instance].state.generic + == OpenSHC::Map::Units::States::US_STAND_UPUnk))) { + continue; + } + switch (_priority) { + case 0: + if (this->units[DAT_CurrentUnitSlotID::instance].owner + == DAT_GameSynchronyState::instance.currentPlayerSlotID) { + if (this->units[DAT_CurrentUnitSlotID::instance].unitType != OpenSHC::Map::Units::UT_LORD + || _lordUnitID != 0) { + this->units[DAT_CurrentUnitSlotID::instance].isSelected = 1; + this->totalUnitsInSelection = this->totalUnitsInSelection + 1; + } + } + break; + case 1: + if (this->units[DAT_CurrentUnitSlotID::instance].owner + == DAT_GameSynchronyState::instance.currentPlayerSlotID) { + if (this->units[DAT_CurrentUnitSlotID::instance].unitType + == OpenSHC::Map::Units::UT_S_CATAPULT) { + this->units[DAT_CurrentUnitSlotID::instance].isSelected = 1; + this->totalUnitsInSelection = this->totalUnitsInSelection + 1; + } + } + break; + case 2: + if (this->units[DAT_CurrentUnitSlotID::instance].owner + == DAT_GameSynchronyState::instance.currentPlayerSlotID) { + if (this->units[DAT_CurrentUnitSlotID::instance].unitType + == OpenSHC::Map::Units::UT_S_TREBUCHET) { + this->units[DAT_CurrentUnitSlotID::instance].isSelected = 1; + this->totalUnitsInSelection = this->totalUnitsInSelection + 1; + } + } + break; + case 3: + if (this->units[DAT_CurrentUnitSlotID::instance].owner + == DAT_GameSynchronyState::instance.currentPlayerSlotID) { + if (this->units[DAT_CurrentUnitSlotID::instance].unitType == OpenSHC::Map::Units::UT_S_TOWER) { + this->units[DAT_CurrentUnitSlotID::instance].isSelected = 1; + this->totalUnitsInSelection = this->totalUnitsInSelection + 1; + } + } + break; + case 4: + if (this->units[DAT_CurrentUnitSlotID::instance].owner + == DAT_GameSynchronyState::instance.currentPlayerSlotID) { + if (this->units[DAT_CurrentUnitSlotID::instance].unitType + == OpenSHC::Map::Units::UT_S_BATTERINGRAM) { + this->units[DAT_CurrentUnitSlotID::instance].isSelected = 1; + this->totalUnitsInSelection = this->totalUnitsInSelection + 1; + } + } + break; + case 5: + if (this->units[DAT_CurrentUnitSlotID::instance].owner + == DAT_GameSynchronyState::instance.currentPlayerSlotID) { + if (this->units[DAT_CurrentUnitSlotID::instance].unitType == OpenSHC::Map::Units::UT_S_SHIELD) { + this->units[DAT_CurrentUnitSlotID::instance].isSelected = 1; + this->totalUnitsInSelection = this->totalUnitsInSelection + 1; + } + } + break; + case 6: + if (this->units[DAT_CurrentUnitSlotID::instance].owner + == DAT_GameSynchronyState::instance.currentPlayerSlotID) { + if (this->units[DAT_CurrentUnitSlotID::instance].unitType + == OpenSHC::Map::Units::UT_S_MANGONEL) { + this->units[DAT_CurrentUnitSlotID::instance].isSelected = 1; + this->totalUnitsInSelection = this->totalUnitsInSelection + 1; + } + } + break; + case 7: + if (this->units[DAT_CurrentUnitSlotID::instance].owner + == DAT_GameSynchronyState::instance.currentPlayerSlotID) { + if (this->units[DAT_CurrentUnitSlotID::instance].unitType + == OpenSHC::Map::Units::UT_S_BALLISTA) { + this->units[DAT_CurrentUnitSlotID::instance].isSelected = 1; + this->totalUnitsInSelection = this->totalUnitsInSelection + 1; + } + } + break; + case 8: + if (this->units[DAT_CurrentUnitSlotID::instance].owner + == DAT_GameSynchronyState::instance.currentPlayerSlotID) { + if (this->units[DAT_CurrentUnitSlotID::instance].unitType + == OpenSHC::Map::Units::UT_S_FBALLISTA) { + this->units[DAT_CurrentUnitSlotID::instance].isSelected = 1; + this->totalUnitsInSelection = this->totalUnitsInSelection + 1; + } + } + break; + case 9: + if (this->units[DAT_CurrentUnitSlotID::instance].owner + != DAT_GameSynchronyState::instance.currentPlayerSlotID) { + this->units[DAT_CurrentUnitSlotID::instance].isSelected = 1; + this->totalUnitsInSelection = this->totalUnitsInSelection + 1; + } + } + } + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 11bde65af..af787fa46 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -50821,7 +50821,7 @@ SHC_3BB0A8C1_0x005345D0 | 0.0% | Pending SHC_3BB0A8C1_0x005346D0 | 32.1% | orig walks unit ptr -SHC_3BB0A8C1_0x005347E0 | 0.0% | Pending +SHC_3BB0A8C1_0x005347E0 | 61.8% | cases 1-8 dead in binary SHC_3BB0A8C1_0x00534880 | 0.0% | Pending From a4cd6ecdac20fdebe7a594c77cbbadc6166d1311 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 10:08:03 +0200 Subject: [PATCH 182/299] reimplement: SHC_3BB0A8C1_0x005371F0 36.20% orig walks XYPair ptrs --- .../Units/UnitsState/findFreeTileNearby.cpp | 254 ++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 255 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/findFreeTileNearby.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/findFreeTileNearby.cpp b/src/OpenSHC/Map/Units/UnitsState/findFreeTileNearby.cpp new file mode 100644 index 000000000..14d01b5a1 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/findFreeTileNearby.cpp @@ -0,0 +1,254 @@ +#include "OpenSHC/Map/Navigation/DirectionAlgorithmState.func.hpp" +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Map/Buildings/BuildingType.hpp" + +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_DirectionAlgorithmState.hpp" +#include "OpenSHC/Globals/DAT_PathFindingState.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_UnitPropertiesDefinedData.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Map::Buildings::BuildingType; + + // FUNCTION: STRONGHOLDCRUSADER 0x005371F0 + uint UnitsState::findFreeTileNearby(uint unitID, uint tile) + { + dword _areaAtUnit = (short)DAT_TileMapState::instance.PathConnectionLayer[this->units[unitID].tile]; + int _originY = DAT_ViewportRenderState::instance.tileTranslationMatrix_YComponent[tile]; + int _originX = tile - DAT_ViewportRenderState::instance.translationMatrix[_originY].addXgetTile; + /* original_y-2 */ + uint _northTile = DAT_ViewportRenderState::instance.translationMatrix[_originY + -2].addXgetTile + _originX; + if (MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::PathFindingState_Func::calculateCanPlayerUnitsNavigateToAreaFromArea, + DAT_PathFindingState::ptr)(this->units[unitID].owner, _areaAtUnit, + (short)DAT_TileMapState::instance.PathConnectionLayer[_northTile], 0) + == 0) { + _northTile = 0; + } + /* original_x+2 */ + uint _eastTile = DAT_ViewportRenderState::instance.translationMatrix[_originY].addXgetTile + 2 + _originX; + if (MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::PathFindingState_Func::calculateCanPlayerUnitsNavigateToAreaFromArea, + DAT_PathFindingState::ptr)(this->units[unitID].owner, _areaAtUnit, + (short)DAT_TileMapState::instance.PathConnectionLayer[_eastTile], 0) + == 0) { + _eastTile = 0; + } + /* original_y+2 */ + uint _southTile = DAT_ViewportRenderState::instance.translationMatrix[_originY + 2].addXgetTile + _originX; + if (MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::PathFindingState_Func::calculateCanPlayerUnitsNavigateToAreaFromArea, + DAT_PathFindingState::ptr)(this->units[unitID].owner, _areaAtUnit, + (short)DAT_TileMapState::instance.PathConnectionLayer[_southTile], 0) + == 0) { + _southTile = 0; + } + /* original_x-2 */ + uint _westTile = DAT_ViewportRenderState::instance.translationMatrix[_originY].addXgetTile + -2 + _originX; + if (MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::PathFindingState_Func::calculateCanPlayerUnitsNavigateToAreaFromArea, + DAT_PathFindingState::ptr)(this->units[unitID].owner, _areaAtUnit, + (short)DAT_TileMapState::instance.PathConnectionLayer[_westTile], 0) + == 0) { + _westTile = 0; + } + if (_westTile == 0 && _southTile == 0 && _eastTile == 0 && _northTile == 0) { + return 0; + } + if ((_northTile != 0 || _southTile != 0) + && ((DAT_TileMapState::instance + .LogicLayer[DAT_ViewportRenderState::instance.translationMatrix[_originY].addXgetTile + + _originX - 1] + & 0x100) + == 0 + || (DAT_TileMapState::instance + .LogicLayer[DAT_ViewportRenderState::instance.translationMatrix[_originY].addXgetTile + + _originX + 1] + & 0x100) + == 0)) { + _southTile = 0; + _northTile = 0; + } + if ((_westTile != 0 || _eastTile != 0) + && ((DAT_TileMapState::instance + .LogicLayer[DAT_ViewportRenderState::instance.translationMatrix[_originY + -1].addXgetTile + + _originX] + & 0x100) + == 0 + || (DAT_TileMapState::instance + .LogicLayer[DAT_ViewportRenderState::instance.translationMatrix[_originY + 1].addXgetTile + + _originX] + & 0x100) + == 0)) { + _eastTile = 0; + _westTile = 0; + } + if (_northTile != 0) { + for (int i = 0; i < 9; ++i) { + uint _checkX = DAT_UnitPropertiesDefinedData::instance.field120_0x1213c[i].x + _originX; + uint _checkY = DAT_UnitPropertiesDefinedData::instance.field120_0x1213c[i].y + _originY; + if (_checkX >= 400 || _checkY >= 400) { + continue; + } + /* the 400x400 map of placeable tiles at 0x021AEC98 */ + if (*(char*)(_checkX + 0x21aec98 + _checkY * 400) == '\0') { + continue; + } + int _checkTile = DAT_ViewportRenderState::instance.translationMatrix[_checkY].addXgetTile + + DAT_UnitPropertiesDefinedData::instance.field120_0x1213c[i].x + _originX; + if ((DAT_TileMapState::instance.LogicLayer[_checkTile] & 0x100) != 0 + || (DAT_TileMapState::instance.LogicLayer[_checkTile] & 0x4a5014b1) != 0 + || (DAT_TileMapState::instance.BuildingLayer[_checkTile] != 0 + && DAT_BuildingsState::instance + .buildings[DAT_TileMapState::instance.BuildingLayer[_checkTile]] + .buildingType + != OpenSHC::Map::Buildings::BT_KILLINGPIT)) { + _northTile = 0; + break; + } + } + } + if (_eastTile != 0) { + for (int i = 0; i < 9; ++i) { + uint _checkX = DAT_UnitPropertiesDefinedData::instance.field121_0x12184[i].x + _originX; + uint _checkY = DAT_UnitPropertiesDefinedData::instance.field121_0x12184[i].y + _originY; + if (_checkX >= 400 || _checkY >= 400) { + continue; + } + /* the 400x400 map of placeable tiles at 0x021AEC98 */ + if (*(char*)(_checkX + 0x21aec98 + _checkY * 400) == '\0') { + continue; + } + int _checkTile = DAT_ViewportRenderState::instance.translationMatrix[_checkY].addXgetTile + + DAT_UnitPropertiesDefinedData::instance.field121_0x12184[i].x + _originX; + if ((DAT_TileMapState::instance.LogicLayer[_checkTile] & 0x100) != 0 + || (DAT_TileMapState::instance.LogicLayer[_checkTile] & 0x4a5014b1) != 0 + || (DAT_TileMapState::instance.BuildingLayer[_checkTile] != 0 + && DAT_BuildingsState::instance + .buildings[DAT_TileMapState::instance.BuildingLayer[_checkTile]] + .buildingType + != OpenSHC::Map::Buildings::BT_KILLINGPIT)) { + _eastTile = 0; + break; + } + } + } + if (_southTile != 0) { + for (int i = 0; i < 9; ++i) { + uint _checkX = DAT_UnitPropertiesDefinedData::instance.field122_0x121cc[i].x + _originX; + uint _checkY = DAT_UnitPropertiesDefinedData::instance.field122_0x121cc[i].y + _originY; + if (_checkX >= 400 || _checkY >= 400) { + continue; + } + /* the 400x400 map of placeable tiles at 0x021AEC98 */ + if (*(char*)(_checkX + 0x21aec98 + _checkY * 400) == '\0') { + continue; + } + int _checkTile = DAT_ViewportRenderState::instance.translationMatrix[_checkY].addXgetTile + + DAT_UnitPropertiesDefinedData::instance.field122_0x121cc[i].x + _originX; + if ((DAT_TileMapState::instance.LogicLayer[_checkTile] & 0x100) != 0 + || (DAT_TileMapState::instance.LogicLayer[_checkTile] & 0x4a5014b1) != 0 + || (DAT_TileMapState::instance.BuildingLayer[_checkTile] != 0 + && DAT_BuildingsState::instance + .buildings[DAT_TileMapState::instance.BuildingLayer[_checkTile]] + .buildingType + != OpenSHC::Map::Buildings::BT_KILLINGPIT)) { + _southTile = 0; + break; + } + } + } + if (_westTile != 0) { + for (int i = 0; i < 9; ++i) { + uint _checkX = DAT_UnitPropertiesDefinedData::instance.field123_0x12214[i].x + _originX; + uint _checkY = DAT_UnitPropertiesDefinedData::instance.field123_0x12214[i].y + _originY; + if (_checkX >= 400 || _checkY >= 400) { + continue; + } + /* the 400x400 map of placeable tiles at 0x021AEC98 */ + if (*(char*)(_checkX + 0x21aec98 + _checkY * 400) == '\0') { + continue; + } + int _checkTile = DAT_ViewportRenderState::instance.translationMatrix[_checkY].addXgetTile + + DAT_UnitPropertiesDefinedData::instance.field123_0x12214[i].x + _originX; + if ((DAT_TileMapState::instance.LogicLayer[_checkTile] & 0x100) != 0 + || (DAT_TileMapState::instance.LogicLayer[_checkTile] & 0x4a5014b1) != 0 + || (DAT_TileMapState::instance.BuildingLayer[_checkTile] != 0 + && DAT_BuildingsState::instance + .buildings[DAT_TileMapState::instance.BuildingLayer[_checkTile]] + .buildingType + != OpenSHC::Map::Buildings::BT_KILLINGPIT)) { + _westTile = 0; + break; + } + } + } + int _unitY = DAT_ViewportRenderState::instance.tileTranslationMatrix_YComponent[this->units[unitID].tile]; + int _unitX + = this->units[unitID].tile - DAT_ViewportRenderState::instance.translationMatrix[_unitY].addXgetTile; + uint _closestTile = 0; + int _closestDistance = 100000; + if (_northTile != 0) { + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::DirectionAlgorithmState_Func::setAxisBasedDistanceResult, + DAT_DirectionAlgorithmState::ptr)(_northTile + - DAT_ViewportRenderState::instance + .translationMatrix[DAT_ViewportRenderState::instance + .tileTranslationMatrix_YComponent[_northTile]] + .addXgetTile, + DAT_ViewportRenderState::instance.tileTranslationMatrix_YComponent[_northTile], _unitX, _unitY); + if (DAT_DirectionAlgorithmState::instance.distanceHigh < _closestDistance) { + _closestTile = _northTile; + _closestDistance = DAT_DirectionAlgorithmState::instance.distanceHigh; + } + } + if (_southTile != 0) { + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::DirectionAlgorithmState_Func::setAxisBasedDistanceResult, + DAT_DirectionAlgorithmState::ptr)(_southTile + - DAT_ViewportRenderState::instance + .translationMatrix[DAT_ViewportRenderState::instance + .tileTranslationMatrix_YComponent[_southTile]] + .addXgetTile, + DAT_ViewportRenderState::instance.tileTranslationMatrix_YComponent[_southTile], _unitX, _unitY); + if (DAT_DirectionAlgorithmState::instance.distanceHigh < _closestDistance) { + _closestTile = _southTile; + _closestDistance = DAT_DirectionAlgorithmState::instance.distanceHigh; + } + } + if (_eastTile != 0) { + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::DirectionAlgorithmState_Func::setAxisBasedDistanceResult, + DAT_DirectionAlgorithmState::ptr)(_eastTile + - DAT_ViewportRenderState::instance + .translationMatrix[DAT_ViewportRenderState::instance + .tileTranslationMatrix_YComponent[_eastTile]] + .addXgetTile, + DAT_ViewportRenderState::instance.tileTranslationMatrix_YComponent[_eastTile], _unitX, _unitY); + if (DAT_DirectionAlgorithmState::instance.distanceHigh < _closestDistance) { + _closestTile = _eastTile; + _closestDistance = DAT_DirectionAlgorithmState::instance.distanceHigh; + } + } + if (_westTile != 0) { + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::DirectionAlgorithmState_Func::setAxisBasedDistanceResult, + DAT_DirectionAlgorithmState::ptr)(_westTile + - DAT_ViewportRenderState::instance + .translationMatrix[DAT_ViewportRenderState::instance + .tileTranslationMatrix_YComponent[_westTile]] + .addXgetTile, + DAT_ViewportRenderState::instance.tileTranslationMatrix_YComponent[_westTile], _unitX, _unitY); + if (DAT_DirectionAlgorithmState::instance.distanceHigh < _closestDistance) { + _closestTile = _westTile; + _closestDistance = DAT_DirectionAlgorithmState::instance.distanceHigh; + } + } + return _closestTile; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index af787fa46..9909e5297 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -51233,7 +51233,7 @@ SHC_3BB0A8C1_0x005371A0 | 35.7% | param store order differs SHC_3BB0A8C1_0x005371E0 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x005371F0 | 0.0% | Pending +SHC_3BB0A8C1_0x005371F0 | 36.2% | orig walks XYPair ptrs SHC_3BB0A8C1_0x00537700 | 16.1% | orig caches counter local From 85889451200f1f5c95cc638cc0a765c1389ad89b Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 10:10:28 +0200 Subject: [PATCH 183/299] reimplement: SHC_3BB0A8C1_0x00578C40 59.73% branch shape differs --- .../Map/Units/UnitsState/processUnitMove.cpp | 283 ++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 284 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/processUnitMove.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/processUnitMove.cpp b/src/OpenSHC/Map/Units/UnitsState/processUnitMove.cpp new file mode 100644 index 000000000..bee3499fd --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/processUnitMove.cpp @@ -0,0 +1,283 @@ +#include "OpenSHC/Map/Buildings/BuildingsState.func.hpp" +#include "OpenSHC/Map/LandscapeState.func.hpp" +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Rendering/ViewportRenderState.func.hpp" +#include "OpenSHC/Map/Buildings/BuildingType.hpp" +#include "OpenSHC/Map/Units/States/UnitState.hpp" +#include "OpenSHC/Map/Units/UnitType.hpp" +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_CurrentUnitSlotID.hpp" +#include "OpenSHC/Globals/DAT_LandscapeState.hpp" +#include "OpenSHC/Globals/DAT_PathFindingState.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_UnitPropertiesDefinedData.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Map::Buildings::BuildingType; + using OpenSHC::Map::Units::UnitType; + using OpenSHC::Map::Units::States::UnitState; + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x00578C40 + undefined4 UnitsState::processUnitMove(int unitID, int speedCategory) + { + if (this->units[unitID].unitType != OpenSHC::Map::Units::UT_BURNINGMAN) { + if (this->units[unitID].unitType == OpenSHC::Map::Units::UT_A_ASSASSIN + && (this->units[unitID].state.generic == OpenSHC::Map::Units::States::US_ASSASSIN_THROWING_HOOK + || this->units[unitID].state.generic + == OpenSHC::Map::Units::States::US_ASSASSIN_START_CLIMBING_DOWN + || this->units[unitID].state.generic == OpenSHC::Map::Units::States::US_ASSASSIN_CLIMBING_UP + || this->units[unitID].state.generic + == OpenSHC::Map::Units::States::US_ASSASSIN_CLIMBING_DOWN)) { + return 0; + } + if (this->units[unitID].dying != 0) { + return 0; + } + } + if (this->units[unitID].tunnelerFinishedDigging == 5) { + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::setupUnitSharingCurrentTilePosition, this)( + unitID); + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::commitPendingUnitPosition, this)(unitID); + this->units[unitID].field39_0x58 = 0; + return 0; + } + if (this->units[unitID].tunnelerFinishedDigging != 4 && this->units[unitID].tunnelerFinishedDigging != 2) { + this->units[unitID].movementRelated = 8; + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::updateMicroPosition, this)(unitID); + if (this->units[unitID].climbDataID != 0 + && MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::updateClimbing, this)(unitID) == FALSE) { + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::setDestinationForUnit, this)( + unitID, this->units[unitID].destinationX_2Unk, this->units[unitID].destinationY_2Unk, 0); + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::changeDestinationByLeftover, this)(unitID); + } + return 0; + } + this->units[unitID].field39_0x58 = 0; + if (this->units[unitID].moveInstructionSpeedDelayTracker != 0) { + this->units[unitID].moveInstructionSpeedDelayTracker + = this->units[unitID].moveInstructionSpeedDelayTracker - 1; + } + if (this->units[unitID].moveDelay < 2) { + this->units[unitID].moveDelay = 0; + } else { + this->units[unitID].moveDelay = this->units[unitID].moveDelay - 2; + } + int _steps = speedCategory + this->units[unitID].field259_0x3d2; + for (int _step = 0; _step <= _steps; ++_step) { + if (this->units[DAT_CurrentUnitSlotID::instance].field180_0x32d == '\x01') { + if (this->units[DAT_CurrentUnitSlotID::instance].field218_0x37e < 4 + || this->units[DAT_CurrentUnitSlotID::instance].field218_0x37e > 0xb) { + continue; + } + } else if (this->units[DAT_CurrentUnitSlotID::instance].field180_0x32d == '\x02') { + if (this->units[DAT_CurrentUnitSlotID::instance].field218_0x37e <= 4) { + continue; + } + if (this->units[DAT_CurrentUnitSlotID::instance].field218_0x37e >= 10) { + if (this->units[DAT_CurrentUnitSlotID::instance].field218_0x37e > 0xb) { + this->units[DAT_CurrentUnitSlotID::instance].field218_0x37e = 3; + } + continue; + } + } + this->units[unitID].movementRelated = this->units[unitID].movementRelated + 1; + this->units[unitID].field105_0xe8 = 0; + if (this->units[unitID].movementRelated < 8) { + if (DAT_UnitPropertiesDefinedData::instance.field79_0x119cc[this->units[unitID].facingDirection] + <= this->units[unitID].movementRelated) { + this->units[unitID].field105_0xe8 = 1; + } + } else { + ushort _pathIndex = this->units[unitID].currentIndexInPathPlan; + if (this->units[unitID].totalSizeOfPathPlan <= (short)_pathIndex + && this->units[unitID].field280_0x3f4 == 0) { + this->units[unitID].unknownMovementRelated_0x2d2 = 0; + this->units[unitID].tunnelerFinishedDigging = 0; + this->units[unitID].movementRelated = 8; + this->units[unitID].destinationX_2Unk = this->units[unitID].x; + this->units[unitID].destinationY_2Unk = this->units[unitID].y; + return 0; + } + this->units[unitID].movementRelated = 0; + uint _direction = (char)this->units[unitID].pathPlanStart[(short)_pathIndex / 2]; + if ((_pathIndex & 1) == 0) { + _direction = _direction & 0xf; + } else { + _direction = (int)_direction >> 4; + } + this->units[unitID].facingDirection = (short)_direction; + if (this->units[unitID].field280_0x3f4 == 0) { + this->units[unitID].currentIndexInPathPlan = _pathIndex + 1; + } + if (this->units[unitID].field259_0x3d2 != 0) { + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::saveUnitStateBeforeInterruption, this)( + unitID); + this->units[unitID].movementRelated = 8; + this->units[unitID].lookForEnemy = 0; + this->units[unitID].state.generic = OpenSHC::Map::Units::States::US_MELEE_ATTACK; + this->units[unitID].SA = 0; + this->units[unitID].animationCycleNumber = 0; + return 0; + } + if (this->units[unitID].moveRelatedFlag != 1) { + if (this->units[unitID].field280_0x3f4 != 0 + || MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::doMoveFromTileToTile, + DAT_PathFindingState::ptr)(unitID, this->units[unitID].tile, this->units[unitID].y, + _direction, this->units[unitID].moveRelatedFlag, this->units[unitID].cannotClimb) + == FALSE) { + this->units[unitID].movementRelated = 8; + if (this->units[unitID].field280_0x3f4 > 0) { + this->units[unitID].field280_0x3f4 = this->units[unitID].field280_0x3f4 - 1; + if (this->units[unitID].field280_0x3f4 > 0) { + return 0; + } + } + this->unknownInitially0_01 = this->unknownInitially0_01 + 1; + short _destinationY = this->units[unitID].destinationYPosition; + short _destinationX = this->units[unitID].destinationXPosition; + bool _destinationReachable = false; + if (MACRO_CALL_MEMBER(OpenSHC::Rendering::ViewportRenderState_Func::xyAreValid, + DAT_ViewportRenderState::ptr)(_destinationX, _destinationY) + == FALSE) { + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func:: + makeUnitStopWalkingByClearingPathProgressState, + this)(unitID); + } else if ((short)DAT_TileMapState::instance + .PathConnectionLayer[DAT_ViewportRenderState::instance + .translationMatrix[_destinationY] + .addXgetTile + + _destinationX] + != 0) { + if (MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func:: + calculateCanPlayerUnitsNavigateToAreaFromArea, + DAT_PathFindingState::ptr)(this->units[unitID].owner, + (short)DAT_TileMapState::instance.PathConnectionLayer[this->units[unitID].tile], + (short)DAT_TileMapState::instance + .PathConnectionLayer[DAT_ViewportRenderState::instance + .translationMatrix[_destinationY] + .addXgetTile + + _destinationX], + 0) + != 0) { + _destinationReachable = true; + } + } + if (!_destinationReachable) { + if (this->units[unitID].unitType == OpenSHC::Map::Units::UT_LORD) { + return 0; + } + if (this->units[unitID].isSelectable_OR_matchTime != 0) { + return 0; + } + if (this->units[unitID].unitType == OpenSHC::Map::Units::UT_CAGEDOG) { + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func:: + makeUnitStopWalkingByClearingPathProgressState, + this)(unitID); + return 0; + } + if (this->units[unitID].state.generic != OpenSHC::Map::Units::States::US_DISAPPEAR) { + this->units[unitID].state.generic = OpenSHC::Map::Units::States::US_DISAPPEAR; + this->units[unitID].updateTickTracker = 0; + return 0; + } + } + if (MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::setDestinationForUnit, this)( + DAT_CurrentUnitSlotID::instance, this->units[unitID].destinationXPosition, + this->units[unitID].destinationYPosition, 0) + == FALSE) { + this->units[unitID].field280_0x3f4 = 0x28; + return 0; + } + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::changeDestinationByLeftover, this)( + unitID); + return 0; + } + MACRO_CALL_MEMBER(OpenSHC::Map::LandscapeState_Func::spawnCrowFromNearbyTree, + DAT_LandscapeState::ptr)(unitID); + } + this->units[unitID].currentTilePosition_2Unk = this->units[unitID].tile; + this->units[unitID].nextTileUnk + = DAT_TileMapState::instance.directionTranslationMatrix[this->units[unitID].y][_direction] + + this->units[unitID].tile; + this->units[unitID].mimicCurrentXPosition + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction].short_.xOffset + + this->units[unitID].x; + this->units[unitID].mimicCurrentYPosition + = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[_direction].short_.yOffset + + this->units[unitID].y; + this->units[unitID].microXPosition = this->units[unitID].x * 8 + 4; + this->units[unitID].microYPosition = this->units[unitID].y * 8 + 4; + } + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::setupUnitSharingCurrentTilePosition, this)( + unitID); + switch (this->units[unitID].facingDirection) { + case 0: + this->units[unitID].microYPosition = this->units[unitID].microYPosition - 1; + break; + case 1: + this->units[unitID].microYPosition = this->units[unitID].microYPosition - 1; + case 2: + this->units[unitID].microXPosition = this->units[unitID].microXPosition + 1; + break; + case 3: + this->units[unitID].microYPosition = this->units[unitID].microYPosition + 1; + this->units[unitID].microXPosition = this->units[unitID].microXPosition + 1; + break; + case 4: + this->units[unitID].microYPosition = this->units[unitID].microYPosition + 1; + break; + case 5: + this->units[unitID].microYPosition = this->units[unitID].microYPosition + 1; + case 6: + this->units[unitID].microXPosition = this->units[unitID].microXPosition - 1; + break; + case 7: + this->units[unitID].microYPosition = this->units[unitID].microYPosition - 1; + this->units[unitID].microXPosition = this->units[unitID].microXPosition - 1; + } + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::commitPendingUnitPosition, this)(unitID); + if (this->units[unitID].field105_0xe8 == 0) { + MACRO_CALL_MEMBER( + OpenSHC::Map::Units::UnitsState_Func:: + adjustUnitMapOrientationRelatedPositionBasedOnMapOrientationCorrectedFacingDirection, + this)(unitID); + } else { + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::updateMicroPosition, this)(unitID); + MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::processDamageFromKillingPit, + DAT_BuildingsState::ptr)(unitID); + if (DAT_TileMapState::instance.BuildingLayer[this->units[unitID].tile] != 0 + && (DAT_BuildingsState::instance + .buildings[DAT_TileMapState::instance.BuildingLayer[this->units[unitID].tile]] + .buildingType + == OpenSHC::Map::Buildings::BT_TOWER1 + || DAT_BuildingsState::instance + .buildings[DAT_TileMapState::instance.BuildingLayer[this->units[unitID].tile]] + .buildingType + == OpenSHC::Map::Buildings::BT_TOWER4)) { + DAT_BuildingsState::instance + .buildings[DAT_TileMapState::instance.BuildingLayer[this->units[unitID].tile]] + .hasUnitsOntop = 1; + DAT_BuildingsState::instance + .buildings[DAT_TileMapState::instance.BuildingLayer[this->units[unitID].tile]] + .field261_0x2fa = 100; + } + } + this->units[unitID].field105_0xe8 = 0; + MACRO_CALL_MEMBER( + OpenSHC::Map::Units::UnitsState_Func::updateUnitFadeAndVisibilityNearStructures, this)(unitID); + } + return 1; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 9909e5297..f7b1f659b 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -66971,7 +66971,7 @@ SHC_3BB0A8C1_0x00578370 | 0.0% | Pending SHC_3BB0A8C1_0x00578B40 | 0.0% | Pending -SHC_3BB0A8C1_0x00578C40 | 0.0% | Pending +SHC_3BB0A8C1_0x00578C40 | 59.7% | branch shape differs SHC_3BB0A8C1_0x00578D90 | 0.0% | Pending From 706f73b93d5b600ca03f8522f1bc04ac5d30669c Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 10:12:19 +0200 Subject: [PATCH 184/299] reimplement: SHC_3BB0A8C1_0x00531220 31.00% orig shares sfx tails --- .../UnitsState/processUnitAttackOtherUnit.cpp | 334 ++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 335 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/processUnitAttackOtherUnit.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/processUnitAttackOtherUnit.cpp b/src/OpenSHC/Map/Units/UnitsState/processUnitAttackOtherUnit.cpp new file mode 100644 index 000000000..4bbe52bac --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/processUnitAttackOtherUnit.cpp @@ -0,0 +1,334 @@ +#include "OpenSHC/Audio/MSS/SoundSystem.func.hpp" +#include "OpenSHC/Audio/SFX/SFXState.func.hpp" +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Audio/SFX/SoundEffectID.hpp" +#include "OpenSHC/DE/SHCDE/eSFX.hpp" +#include "OpenSHC/Game/GameMode.hpp" +#include "OpenSHC/Map/Units/States/UnitState.hpp" +#include "OpenSHC/Map/Units/UnitType.hpp" + +#include "OpenSHC/Globals/DAT_GameSynchronyState.hpp" +#include "OpenSHC/Globals/DAT_SFXState.hpp" +#include "OpenSHC/Globals/DAT_SoundSystemState.hpp" +#include "OpenSHC/Globals/DAT_TribesState.hpp" +#include "OpenSHC/Globals/DAT_UnitPropertiesDefinedData.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Audio::SFX::SoundEffectID; + using OpenSHC::DE::SHCDE::eSFX; + using OpenSHC::Game::GameMode; + using OpenSHC::Map::Units::UnitType; + using OpenSHC::Map::Units::States::UnitState; + + // FUNCTION: STRONGHOLDCRUSADER 0x00531220 + undefined4 UnitsState::processUnitAttackOtherUnit(int unitID, int unit2ID) + { + int _tribeID = this->units[unit2ID].tribeID; + /* get the unit type of unit2 */ + UnitTypeShort _unit2Type = this->units[unit2ID].unitType; + /* get the damage from the array based: row is unit1ID type, column is unit2ID type */ + int _damage = DAT_UnitPropertiesDefinedData::instance + .MELEE_DAMAGE[(short)this->units[unitID].unitType][(short)_unit2Type]; + /* if unit 1 is not a lord */ + if (this->units[unitID].unitType != OpenSHC::Map::Units::UT_LORD) { + _damage = MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::computeDamageFearFactorBonus, this)( + _damage, this->units[unitID].owner); + } + if (this->units[unitID].owner != 0 && this->units[unit2ID].owner != this->units[unitID].owner) { + this->units[unit2ID].lastEncounteredEnemyPlayerID = this->units[unitID].owner; + /* let unit 2 know we attacked them? */ + this->units[unit2ID].lastEncounteredEnemyUnitIDUnk = (short)unitID; + } + /* decrement the health of unit 2 by damage */ + this->units[unit2ID].health = this->units[unit2ID].health - _damage; + if (this->units[unit2ID].health < 1) { + this->units[unit2ID].health = 0; + } + /* compute the health bar in percentages */ + if (this->units[unit2ID].maxHealth == 0) { + this->units[unit2ID].healthPercentage = 100; + } else { + this->units[unit2ID].healthPercentage + = (short)((this->units[unit2ID].health * 100) / this->units[unit2ID].maxHealth); + } + this->units[unit2ID].healthbar = this->units[unit2ID].healthPercentage / 10; + if (this->units[unit2ID].health <= 0 && this->units[unit2ID].isStalked != 0) { + eSFX _hitEffect; + bool _hasHitEffect = true; + switch (this->units[unitID].unitType) { + case OpenSHC::Map::Units::UT_WOODCUTTER: + case OpenSHC::Map::Units::UT_LORD: + _hitEffect = OpenSHC::DE::SHCDE::FX_LORD_HIT; + break; + case OpenSHC::Map::Units::UT_E_SPEAR: + case OpenSHC::Map::Units::UT_A_ARCHER: + case OpenSHC::Map::Units::UT_A_SLINGER: + case OpenSHC::Map::Units::UT_A_HARCHER: + case OpenSHC::Map::Units::UT_A_FIRETHROWER: + _hitEffect = OpenSHC::DE::SHCDE::FX_SPEAR_HIT; + break; + case OpenSHC::Map::Units::UT_E_PIKE: + _hitEffect = OpenSHC::DE::SHCDE::FX_PIKE_HIT; + break; + case OpenSHC::Map::Units::UT_E_MACE: + _hitEffect = OpenSHC::DE::SHCDE::FX_MACE_HIT; + break; + 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: + _hitEffect = OpenSHC::DE::SHCDE::FX_SWORD_HIT; + break; + default: + _hasHitEffect = false; + } + if (_hasHitEffect) { + MACRO_CALL_MEMBER(OpenSHC::Audio::SFX::SFXState_Func::playSFXAtLocation, DAT_SFXState::ptr)( + this->units[unitID].x, this->units[unitID].y, _hitEffect); + } + } + if (this->units[unit2ID].health > 0) { + if (DAT_GameSynchronyState::instance.currentGameMode != OpenSHC::Game::GM_SOLITARY + && this->units[unit2ID].owner == DAT_GameSynchronyState::instance.currentPlayerSlotID) { + MACRO_CALL_MEMBER(OpenSHC::Audio::SFX::SFXState_Func::playSFXWeAreUnderAttack, DAT_SFXState::ptr)(); + } + return 0; + } + this->units[unit2ID].dying = 1; + if (_tribeID > 0) { + DAT_TribesState::instance.tribes[_tribeID].field133_0x278 = 1; + } + this->units[unit2ID].animationCycleNumber = 0; + if (this->units[unitID].unitType == OpenSHC::Map::Units::UT_E_SWORD) { + this->units[unit2ID].state.generic = OpenSHC::Map::Units::States::US_DEATH_03; + } else if (this->units[unitID].unitType == OpenSHC::Map::Units::UT_E_KNIGHT) { + this->units[unit2ID].state.generic = OpenSHC::Map::Units::States::US_DEATH_03; + } else if (this->units[unitID].unitType == OpenSHC::Map::Units::UT_E_SPEAR) { + this->units[unit2ID].state.generic = OpenSHC::Map::Units::States::US_DEATH_03; + } else if (this->units[unitID].unitType == OpenSHC::Map::Units::UT_E_PIKE) { + this->units[unit2ID].state.generic = OpenSHC::Map::Units::States::US_DEATH_03; + } else if (this->units[unitID].unitType == OpenSHC::Map::Units::UT_E_XBOW) { + this->units[unit2ID].state.generic = OpenSHC::Map::Units::States::US_DEATH_03; + } else if (this->units[unitID].unitType == OpenSHC::Map::Units::UT_E_ARCHER) { + this->units[unit2ID].state.generic = OpenSHC::Map::Units::States::US_DEATH_03; + } else if (this->units[unitID].unitType == OpenSHC::Map::Units::UT_A_ARCHER) { + this->units[unit2ID].state.generic = OpenSHC::Map::Units::States::US_DEATH_03; + } else if (this->units[unitID].unitType == OpenSHC::Map::Units::UT_A_ASSASSIN) { + this->units[unit2ID].state.generic = OpenSHC::Map::Units::States::US_DEATH_03; + } else if (this->units[unitID].unitType == OpenSHC::Map::Units::UT_A_HARCHER) { + this->units[unit2ID].state.generic = OpenSHC::Map::Units::States::US_DEATH_03; + } else if (this->units[unitID].unitType == OpenSHC::Map::Units::UT_A_SWORDSMAN) { + this->units[unit2ID].state.generic = OpenSHC::Map::Units::States::US_DEATH_03; + } else { + this->units[unit2ID].state.generic + = (this->units[unitID].unitType != OpenSHC::Map::Units::UT_A_FIRETHROWER) + + OpenSHC::Map::Units::States::US_DEATH_03; + } + uint _deathVariant = this->units[unit2ID].fixedRng & 1; + this->units[unit2ID].tunnelerFinishedDigging = 1; + if (this->units[unit2ID].isStalked != 0) { + return 1; + } + switch (_unit2Type) { + case OpenSHC::Map::Units::UT_S_CATAPULT: + case OpenSHC::Map::Units::UT_S_MANGONEL: + case OpenSHC::Map::Units::UT_S_TOWER: + case OpenSHC::Map::Units::UT_S_BATTERINGRAM: + case OpenSHC::Map::Units::UT_S_BALLISTA: + case OpenSHC::Map::Units::UT_S_FBALLISTA: + MACRO_CALL_MEMBER(OpenSHC::Audio::SFX::SFXState_Func::playSFXAtLocation, DAT_SFXState::ptr)( + this->units[unit2ID].x, this->units[unit2ID].y, OpenSHC::DE::SHCDE::FX_SIEGE_DIE); + return 1; + case OpenSHC::Map::Units::UT_S_TREBUCHET: + MACRO_CALL_MEMBER(OpenSHC::Audio::SFX::SFXState_Func::playSFXAtLocation, DAT_SFXState::ptr)( + this->units[unit2ID].x, this->units[unit2ID].y, OpenSHC::DE::SHCDE::FX_TR_DIE); + return 1; + case OpenSHC::Map::Units::UT_S_SHIELD: + if (this->units[unitID].digTileX__OR__countCurrentlyManningEnginers__OR__forCowsRandomBelow300 > 0) { + MACRO_CALL_MEMBER(OpenSHC::Audio::SFX::SFXState_Func::playSFXAtLocation, DAT_SFXState::ptr)( + this->units[unit2ID].x, this->units[unit2ID].y, OpenSHC::DE::SHCDE::FX_BODY_HIT); + return 1; + } + MACRO_CALL_MEMBER(OpenSHC::Audio::SFX::SFXState_Func::playSFXAtLocation, DAT_SFXState::ptr)( + this->units[unit2ID].x, this->units[unit2ID].y, OpenSHC::DE::SHCDE::FX_SIEGE_DIE); + return 1; + } + bool _hasSpecialDeathSound = false; + if (_unit2Type == OpenSHC::Map::Units::UT_BREWER || _unit2Type == OpenSHC::Map::Units::UT_TANNER + || _unit2Type == OpenSHC::Map::Units::UT_LADY || _unit2Type == OpenSHC::Map::Units::UT_MOTHER + || (_unit2Type == OpenSHC::Map::Units::UT_CHILD && this->units[unitID].spriteID == 0x81)) { + _hasSpecialDeathSound = true; + MACRO_CALL_MEMBER(OpenSHC::Audio::SFX::SFXState_Func::playSFXAtLocation, DAT_SFXState::ptr)( + this->units[unit2ID].x, this->units[unit2ID].y, OpenSHC::DE::SHCDE::FX_GIRL_DIE); + } + if (_unit2Type == OpenSHC::Map::Units::UT_LORD) { + if (this->units[unit2ID].owner == DAT_GameSynchronyState::instance.currentPlayerSlotID) { + MACRO_CALL_MEMBER(OpenSHC::Audio::SFX::SFXState_Func::setUpSFXToPlayUnk, DAT_SFXState::ptr)( + OpenSHC::Audio::SFX::SEID_PLAYER_LORD_DEATH); + if (DAT_GameSynchronyState::instance.currentGameMode == OpenSHC::Game::GM_SOLITARY) { + MACRO_CALL_MEMBER( + OpenSHC::Audio::MSS::SoundSystem_Func::setSomeSoundTime, DAT_SoundSystemState::ptr)(); + } + } else { + MACRO_CALL_MEMBER(OpenSHC::Audio::SFX::SFXState_Func::setUpSFXToPlayUnk, DAT_SFXState::ptr)( + OpenSHC::Audio::SFX::SEID_AI_LORD_DEATH); + } + _hasSpecialDeathSound = true; + } else if (_unit2Type == OpenSHC::Map::Units::UT_JESTER) { + MACRO_CALL_MEMBER(OpenSHC::Audio::SFX::SFXState_Func::playSFXAtLocation, DAT_SFXState::ptr)( + this->units[unit2ID].x, this->units[unit2ID].y, OpenSHC::DE::SHCDE::FX_JESTER_DIE); + _hasSpecialDeathSound = true; + } + switch (this->units[unitID].unitType) { + case OpenSHC::Map::Units::UT_WOODCUTTER: + if (_hasSpecialDeathSound) { + MACRO_CALL_MEMBER(OpenSHC::Audio::SFX::SFXState_Func::playSFXAtLocation, DAT_SFXState::ptr)( + this->units[unit2ID].x, this->units[unit2ID].y, OpenSHC::DE::SHCDE::FX_LORD_HIT); + return 1; + } + MACRO_CALL_MEMBER(OpenSHC::Audio::SFX::SFXState_Func::playSFXAtLocation, DAT_SFXState::ptr)( + this->units[unit2ID].x, this->units[unit2ID].y, OpenSHC::DE::SHCDE::FX_LORD_KILL); + return 1; + case OpenSHC::Map::Units::UT_E_SPEAR: + case OpenSHC::Map::Units::UT_A_ARCHER: + case OpenSHC::Map::Units::UT_A_SLINGER: + case OpenSHC::Map::Units::UT_A_HARCHER: + case OpenSHC::Map::Units::UT_A_FIRETHROWER: + if (_hasSpecialDeathSound) { + MACRO_CALL_MEMBER(OpenSHC::Audio::SFX::SFXState_Func::playSFXAtLocation, DAT_SFXState::ptr)( + this->units[unit2ID].x, this->units[unit2ID].y, OpenSHC::DE::SHCDE::FX_SPEAR_HIT); + return 1; + } + if (_deathVariant == 0) { + MACRO_CALL_MEMBER(OpenSHC::Audio::SFX::SFXState_Func::playSFXAtLocation, DAT_SFXState::ptr)( + this->units[unit2ID].x, this->units[unit2ID].y, OpenSHC::DE::SHCDE::FX_DEATH_SPEAR); + return 1; + } + if (_deathVariant == 1) { + MACRO_CALL_MEMBER(OpenSHC::Audio::SFX::SFXState_Func::playSFXAtLocation, DAT_SFXState::ptr)( + this->units[unit2ID].x, this->units[unit2ID].y, OpenSHC::DE::SHCDE::FX_DEATH_SPEAR2); + return 1; + } + return 1; + case OpenSHC::Map::Units::UT_E_PIKE: + if (_hasSpecialDeathSound) { + MACRO_CALL_MEMBER(OpenSHC::Audio::SFX::SFXState_Func::playSFXAtLocation, DAT_SFXState::ptr)( + this->units[unit2ID].x, this->units[unit2ID].y, OpenSHC::DE::SHCDE::FX_PIKE_HIT); + return 1; + } + if (_deathVariant == 0) { + MACRO_CALL_MEMBER(OpenSHC::Audio::SFX::SFXState_Func::playSFXAtLocation, DAT_SFXState::ptr)( + this->units[unit2ID].x, this->units[unit2ID].y, OpenSHC::DE::SHCDE::FX_DEATH_SPEAR); + return 1; + } + if (_deathVariant == 1) { + MACRO_CALL_MEMBER(OpenSHC::Audio::SFX::SFXState_Func::playSFXAtLocation, DAT_SFXState::ptr)( + this->units[unit2ID].x, this->units[unit2ID].y, OpenSHC::DE::SHCDE::FX_DEATH_SPEAR2); + return 1; + } + return 1; + case OpenSHC::Map::Units::UT_E_MACE: + if (_hasSpecialDeathSound) { + MACRO_CALL_MEMBER(OpenSHC::Audio::SFX::SFXState_Func::playSFXAtLocation, DAT_SFXState::ptr)( + this->units[unit2ID].x, this->units[unit2ID].y, OpenSHC::DE::SHCDE::FX_MACE_HIT); + return 1; + } + if (_deathVariant == 0) { + MACRO_CALL_MEMBER(OpenSHC::Audio::SFX::SFXState_Func::playSFXAtLocation, DAT_SFXState::ptr)( + this->units[unit2ID].x, this->units[unit2ID].y, OpenSHC::DE::SHCDE::FX_DEATH_CLUB); + return 1; + } + if (_deathVariant == 1) { + MACRO_CALL_MEMBER(OpenSHC::Audio::SFX::SFXState_Func::playSFXAtLocation, DAT_SFXState::ptr)( + this->units[unit2ID].x, this->units[unit2ID].y, OpenSHC::DE::SHCDE::FX_DEATH_CLUB2); + return 1; + } + return 1; + 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: + if (_hasSpecialDeathSound) { + MACRO_CALL_MEMBER(OpenSHC::Audio::SFX::SFXState_Func::playSFXAtLocation, DAT_SFXState::ptr)( + this->units[unit2ID].x, this->units[unit2ID].y, OpenSHC::DE::SHCDE::FX_SWORD_HIT); + return 1; + } + if (_deathVariant == 0) { + MACRO_CALL_MEMBER(OpenSHC::Audio::SFX::SFXState_Func::playSFXAtLocation, DAT_SFXState::ptr)( + this->units[unit2ID].x, this->units[unit2ID].y, OpenSHC::DE::SHCDE::FX_DEATH_SWORD); + return 1; + } + if (_deathVariant == 1) { + MACRO_CALL_MEMBER(OpenSHC::Audio::SFX::SFXState_Func::playSFXAtLocation, DAT_SFXState::ptr)( + this->units[unit2ID].x, this->units[unit2ID].y, OpenSHC::DE::SHCDE::FX_DEATH_SWORD2); + return 1; + } + return 1; + case OpenSHC::Map::Units::UT_LORD: + if (_hasSpecialDeathSound) { + MACRO_CALL_MEMBER(OpenSHC::Audio::SFX::SFXState_Func::playSFXAtLocation, DAT_SFXState::ptr)( + this->units[unit2ID].x, this->units[unit2ID].y, OpenSHC::DE::SHCDE::FX_LORD_HIT); + return 1; + } + if (this->units[unitID].unknownLordTypeBasedMissionSpecificValue_01 == 0) { + MACRO_CALL_MEMBER(OpenSHC::Audio::SFX::SFXState_Func::playSFXAtLocation, DAT_SFXState::ptr)( + this->units[unit2ID].x, this->units[unit2ID].y, OpenSHC::DE::SHCDE::FX_LORD_KILL); + return 1; + } + MACRO_CALL_MEMBER(OpenSHC::Audio::SFX::SFXState_Func::playSFXAtLocation, DAT_SFXState::ptr)( + this->units[unit2ID].x, this->units[unit2ID].y, OpenSHC::DE::SHCDE::FX_ARAB_LORD_KILL); + return 1; + default: + if (_hasSpecialDeathSound) { + return 1; + } + if ((this->units[unit2ID].fixedRng & 7) == 0) { + MACRO_CALL_MEMBER(OpenSHC::Audio::SFX::SFXState_Func::playSFXAtLocation, DAT_SFXState::ptr)( + this->units[unit2ID].x, this->units[unit2ID].y, OpenSHC::DE::SHCDE::FX_BODY_HIT); + return 1; + } + if ((this->units[unit2ID].fixedRng & 7) == 1) { + MACRO_CALL_MEMBER(OpenSHC::Audio::SFX::SFXState_Func::playSFXAtLocation, DAT_SFXState::ptr)( + this->units[unit2ID].x, this->units[unit2ID].y, OpenSHC::DE::SHCDE::FX_BODY_HIT2); + return 1; + } + if ((this->units[unit2ID].fixedRng & 7) == 2) { + MACRO_CALL_MEMBER(OpenSHC::Audio::SFX::SFXState_Func::playSFXAtLocation, DAT_SFXState::ptr)( + this->units[unit2ID].x, this->units[unit2ID].y, OpenSHC::DE::SHCDE::FX_BODY_HIT3); + return 1; + } + if ((this->units[unit2ID].fixedRng & 7) == 3) { + MACRO_CALL_MEMBER(OpenSHC::Audio::SFX::SFXState_Func::playSFXAtLocation, DAT_SFXState::ptr)( + this->units[unit2ID].x, this->units[unit2ID].y, OpenSHC::DE::SHCDE::FX_BODY_HIT4); + return 1; + } + if ((this->units[unit2ID].fixedRng & 7) == 4) { + MACRO_CALL_MEMBER(OpenSHC::Audio::SFX::SFXState_Func::playSFXAtLocation, DAT_SFXState::ptr)( + this->units[unit2ID].x, this->units[unit2ID].y, OpenSHC::DE::SHCDE::FX_BODY_HIT5); + return 1; + } + if ((this->units[unit2ID].fixedRng & 7) == 5) { + MACRO_CALL_MEMBER(OpenSHC::Audio::SFX::SFXState_Func::playSFXAtLocation, DAT_SFXState::ptr)( + this->units[unit2ID].x, this->units[unit2ID].y, OpenSHC::DE::SHCDE::FX_BODY_HIT6); + return 1; + } + if ((this->units[unit2ID].fixedRng & 7) == 6) { + MACRO_CALL_MEMBER(OpenSHC::Audio::SFX::SFXState_Func::playSFXAtLocation, DAT_SFXState::ptr)( + this->units[unit2ID].x, this->units[unit2ID].y, OpenSHC::DE::SHCDE::FX_BODY_HIT7); + return 1; + } + if ((this->units[unit2ID].fixedRng & 7) == 7) { + MACRO_CALL_MEMBER(OpenSHC::Audio::SFX::SFXState_Func::playSFXAtLocation, DAT_SFXState::ptr)( + this->units[unit2ID].x, this->units[unit2ID].y, OpenSHC::DE::SHCDE::FX_BODY_HIT8); + return 1; + } + return 1; + } + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index f7b1f659b..aada8f7b1 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -49665,7 +49665,7 @@ SHC_3BB0A8C1_0x00531000 | 38.3% | orig caches unitTypes local SHC_3BB0A8C1_0x005311F0 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x00531220 | 0.0% | Pending +SHC_3BB0A8C1_0x00531220 | 31.0% | orig shares sfx tails SHC_3BB0A8C1_0x00531814 | 0.0% | Pending From 1bcd150203c512ef17a7dc0d3a326030d73389fc Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 10:15:15 +0200 Subject: [PATCH 185/299] reimplement: SHC_3BB0A8C1_0x0054A7B0 34.03% orig walks enemy array ptr --- .../findNearestEnemyAndHeadTowardsIt.cpp | 370 ++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 371 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/findNearestEnemyAndHeadTowardsIt.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/findNearestEnemyAndHeadTowardsIt.cpp b/src/OpenSHC/Map/Units/UnitsState/findNearestEnemyAndHeadTowardsIt.cpp new file mode 100644 index 000000000..c99838308 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/findNearestEnemyAndHeadTowardsIt.cpp @@ -0,0 +1,370 @@ +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" +#include "OpenSHC/Map/TileMapState.func.hpp" +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Map/Units/Behavior/UnitStanceEnum.hpp" +#include "OpenSHC/Map/Units/States/UnitState.hpp" +#include "OpenSHC/Map/Units/UnitInstructionType.hpp" +#include "OpenSHC/Map/Units/UnitType.hpp" + +#include "OpenSHC/Globals/DAT_GameState.hpp" +#include "OpenSHC/Globals/DAT_PathFindingState.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_TribesState.hpp" +#include "OpenSHC/Globals/DAT_UnitPropertiesDefinedData.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Map::Units::UnitInstructionType; + using OpenSHC::Map::Units::UnitType; + using OpenSHC::Map::Units::Behavior::UnitStanceEnum; + using OpenSHC::Map::Units::States::UnitState; + + // FUNCTION: STRONGHOLDCRUSADER 0x0054A7B0 + dword UnitsState::findNearestEnemyAndHeadTowardsIt(int unitID) + { + int _microX = this->units[unitID].microXPosition; + int _microY = this->units[unitID].microYPosition; + short _playerID = this->units[unitID].owner; + ushort _area = DAT_TileMapState::instance.PathConnectionLayer[this->units[unitID].tile]; + this->unitDistanceComputationResultUnk = 100000; + dword _minDistance = 100000; + dword _chosenRawDistance = 0; + int _bestScore = 100000; + int _foundEnemyID = 0; + int _visionDivisor = 1; + bool _skipStanceSearch = false; + int _stanceBasedRange = 0; + short _isRallying = 0; + if ((this->units[unitID].SA != 0 + || (this->units[unitID].movementType_OR_targetUnitID != 0 + && this->units[unitID].state.generic == OpenSHC::Map::Units::States::US_MOVE_TO_DESTINATION)) + && this->units[unitID].tribeID != 0) { + _isRallying = DAT_TribesState::instance.tribes[this->units[unitID].tribeID].isRallyingUnk; + if (DAT_TribesState::instance.tribes[this->units[unitID].tribeID].unitStance + == OpenSHC::Map::Units::Behavior::USE_DEFENSIVE) { + _stanceBasedRange = 40; + } else if (DAT_TribesState::instance.tribes[this->units[unitID].tribeID].unitStance + == OpenSHC::Map::Units::Behavior::USE_AGGRESSIVE) { + _stanceBasedRange = 200; + } + } + if (this->units[unitID].targetingType == OpenSHC::Map::Units::UIT_UNIT_ATTACK_UNIT) { + _skipStanceSearch = true; + switch (this->units[unitID].unitType) { + case OpenSHC::Map::Units::UT_TUNNELER: + case OpenSHC::Map::Units::UT_E_SPEAR: + case OpenSHC::Map::Units::UT_E_PIKE: + case OpenSHC::Map::Units::UT_E_MACE: + case OpenSHC::Map::Units::UT_E_SWORD: + case OpenSHC::Map::Units::UT_E_KNIGHT: + case OpenSHC::Map::Units::UT_E_MONK: + case OpenSHC::Map::Units::UT_LORD: + case OpenSHC::Map::Units::UT_A_SLAVE: + case OpenSHC::Map::Units::UT_A_ASSASSIN: + case OpenSHC::Map::Units::UT_A_SWORDSMAN: + _skipStanceSearch = false; + if (this->units[unitID].tribeID != 0) { + int _tribeUnitID = DAT_TribesState::instance.tribes[this->units[unitID].tribeID].someUnitID; + if (_tribeUnitID != 0 + && this->units[_tribeUnitID].uid + == DAT_TribesState::instance.tribes[this->units[unitID].tribeID].someUnitUID) { + _skipStanceSearch = true; + break; + } + } + this->units[unitID].targetingType = OpenSHC::Map::Units::UIT_NO_INSTRUCTION_OR_MOVEUnk; + } + } else if (this->units[unitID].targetingType == OpenSHC::Map::Units::UIT_ATTACK_LAND) { + switch (this->units[unitID].unitType) { + case OpenSHC::Map::Units::UT_E_SPEAR: + case OpenSHC::Map::Units::UT_E_PIKE: + case OpenSHC::Map::Units::UT_E_MACE: + case OpenSHC::Map::Units::UT_E_SWORD: + case OpenSHC::Map::Units::UT_E_KNIGHT: + case OpenSHC::Map::Units::UT_E_MONK: + case OpenSHC::Map::Units::UT_A_SLAVE: + case OpenSHC::Map::Units::UT_A_ASSASSIN: + case OpenSHC::Map::Units::UT_A_SWORDSMAN: + if (this->units[unitID].lookForEnemy >= 0 + && this->units[unitID].state.generic != OpenSHC::Map::Units::States::US_MELEE_ATTACK) { + if (this->units[unitID].attackAtTileX == this->units[unitID].x + && this->units[unitID].attackAtTileY == this->units[unitID].y) { + this->units[unitID].targetingType = (UnitInstructionType)0; + break; + } + this->units[unitID].plannedDestinationY = this->units[unitID].attackAtTileY; + this->units[unitID].plannedDestinationX = this->units[unitID].attackAtTileX; + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::setDestinationForUnit, this)( + unitID, this->units[unitID].attackAtTileX, this->units[unitID].attackAtTileY, 0); + int _lookAhead = -(this->units[unitID].totalSizeOfPathPlan / 2); + this->units[unitID].state.generic = OpenSHC::Map::Units::States::US_MOVE_TO_DESTINATION; + if (_lookAhead > -0x33) { + _lookAhead = -0x32; + } + this->units[unitID].lookForEnemy = (short)_lookAhead; + } + _skipStanceSearch = true; + } + } + if (this->units[unitID].isSelectable_OR_matchTime == 0) { + _skipStanceSearch = true; + } + if (DAT_GameState::instance.playerDataArray[_playerID].enemies < 5) { + _visionDivisor = 5; + } else if (DAT_GameState::instance.playerDataArray[_playerID].enemies < 15) { + _visionDivisor = 2; + } + for (int _enemyIndex = 0; _enemyIndex < DAT_GameState::instance.playerDataArray[_playerID].enemies; + ++_enemyIndex) { + int _enemyUnitID = DAT_GameState::instance.playerDataArray[_playerID].enemyIDArray[_enemyIndex]; + int _distanceX; + if (this->units[_enemyUnitID].microXPosition < _microX) { + _distanceX = _microX - this->units[_enemyUnitID].microXPosition; + } else { + _distanceX = this->units[_enemyUnitID].microXPosition - _microX; + } + int _distanceY; + if (this->units[_enemyUnitID].microYPosition < _microY) { + _distanceY = _microY - this->units[_enemyUnitID].microYPosition; + } else { + _distanceY = this->units[_enemyUnitID].microYPosition - _microY; + } + dword _approximateDistance; + if (_distanceX < _distanceY) { + /* pythagorean approximation */ + _approximateDistance = (((_distanceX * 2) / 5) * _distanceX) / _distanceY + _distanceY; + } else if (_distanceX == 0) { + /* fixme: bug: I think this needs to be set not to 0 but to _distanceY */ + _approximateDistance = 0; + } else { + _approximateDistance = (((_distanceY * 2) / 5) * _distanceY) / _distanceX + _distanceX; + } + if ((int)_approximateDistance < (int)_minDistance) { + _minDistance = _approximateDistance; + } + if (this->units[unitID].unitType == OpenSHC::Map::Units::UT_A_ASSASSIN + && this->units[_enemyUnitID].isSelectable_OR_matchTime != 0 + && (int)_approximateDistance < (int)this->unitDistanceComputationResultUnk) { + this->unitDistanceComputationResultUnk = _approximateDistance; + } + if (_skipStanceSearch || _stanceBasedRange == 0 || this->units[unitID].lookForEnemy < 0) { + continue; + } + dword _score = _approximateDistance; + if (this->units[unitID]._someX_2 != 0 && _isRallying == 0 && _stanceBasedRange == 40) { + dword _savedDistanceX; + if (this->units[unitID]._someX_2 * 8 < this->units[_enemyUnitID].microXPosition) { + _savedDistanceX = this->units[_enemyUnitID].microXPosition + this->units[unitID]._someX_2 * -8; + } else { + _savedDistanceX = this->units[unitID]._someX_2 * 8 - this->units[_enemyUnitID].microXPosition; + } + if (this->units[unitID]._someY_2 * 8 < this->units[_enemyUnitID].microYPosition) { + _score = this->units[_enemyUnitID].microYPosition + this->units[unitID]._someY_2 * -8; + } else { + _score = this->units[unitID]._someY_2 * 8 - this->units[_enemyUnitID].microYPosition; + } + if ((int)_score <= (int)_savedDistanceX) { + _score = _savedDistanceX; + } + } + dword _rawDistance = _score; + if ((int)_score > _stanceBasedRange) { + continue; + } + if (this->units[_enemyUnitID].uid + != DAT_GameState::instance.mapAndTime.playerEnemenyUnitUIDShortList[_playerID][_enemyIndex]) { + continue; + } + _score = _score + + DAT_UnitPropertiesDefinedData::instance + .UnitVisionBonus[(this->units[unitID].fixedRng + _enemyUnitID) % 10] + / _visionDivisor; + if (this->units[_enemyUnitID].state.generic == OpenSHC::Map::Units::States::US_MELEE_ATTACK) { + _score = (this->units[_enemyUnitID].attackedBy * 50 + _score) * 2; + if (this->units[_enemyUnitID].attackedBy >= 3) { + continue; + } + } + if (this->units[_enemyUnitID].huntedBy >= 2) { + _score = _score + this->units[_enemyUnitID].huntedBy * 0x32; + if (this->units[_enemyUnitID].huntedBy >= 3 + && this->units[unitID].movementType_OR_targetUnitID != _enemyUnitID) { + continue; + } + } + if (this->units[_enemyUnitID].isStalked != 0 + && this->units[_enemyUnitID].unitType != OpenSHC::Map::Units::UT_LIONSHWOLF + && this->units[_enemyUnitID].unitType != OpenSHC::Map::Units::UT_CAGEDOG) { + continue; + } + /* unit type switch */ + switch (this->units[_enemyUnitID].unitType) { + case OpenSHC::Map::Units::UT_PEASANT: + _score = _score * 8 + 200; + break; + 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_A_FIRETHROWER: + break; + case OpenSHC::Map::Units::UT_E_SPEAR: + case OpenSHC::Map::Units::UT_E_PIKE: + case OpenSHC::Map::Units::UT_E_MACE: + case OpenSHC::Map::Units::UT_E_SWORD: + case OpenSHC::Map::Units::UT_E_KNIGHT: + case OpenSHC::Map::Units::UT_E_LADDER: + case OpenSHC::Map::Units::UT_E_MONK: + case OpenSHC::Map::Units::UT_A_SLAVE: + case OpenSHC::Map::Units::UT_A_SLINGER: + case OpenSHC::Map::Units::UT_A_ASSASSIN: + case OpenSHC::Map::Units::UT_A_SWORDSMAN: + _score = _score * 2 + 100; + break; + case OpenSHC::Map::Units::UT_E_ENGINEER: + case OpenSHC::Map::Units::UT_S_CATAPULT: + case OpenSHC::Map::Units::UT_S_TREBUCHET: + case OpenSHC::Map::Units::UT_S_MANGONEL: + 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_S_BALLISTA: + case OpenSHC::Map::Units::UT_S_FBALLISTA: + _score = _score + 0x19; + break; + case OpenSHC::Map::Units::UT_LORD: + _score = (_score + ((int)_score >> 0x1f & 3U)) >> 2; + break; + default: + _score = _score * 4 + 200; + } + if (this->units[unitID].movementType_OR_targetUnitID == _enemyUnitID) { + _score = (int)_score / 2; + } + if ((int)_score >= _bestScore) { + continue; + } + int _enemyTotalHeight + = this->units[_enemyUnitID].buildingHeight + this->units[_enemyUnitID].terrainOrClimbHeight; + int _bestApproachDirection = -1; + int _bestApproachDistance = 10000; + for (int _direction = 0; _direction < 8; ++_direction) { + int _approachTile = DAT_TileMapState::instance.directionTranslationMatrix[this->units[_enemyUnitID] + .y][DAT_UnitPropertiesDefinedData::instance.field84_0x11cb4[_direction]] + + this->units[_enemyUnitID].tile; + if (DAT_TileMapState::instance.UnitLayer[_approachTile] != 0) { + continue; + } + uint _tileHeight = MACRO_CALL_MEMBER( + OpenSHC::Map::TileMapState_Func::getTotalHeightAtTile, DAT_TileMapState::ptr)(_approachTile); + if (_enemyTotalHeight >= (int)(_tileHeight + 0x10)) { + continue; + } + if ((int)(_tileHeight - 0x10) >= _enemyTotalHeight) { + continue; + } + int _approachY = DAT_ViewportRenderState::instance.tileTranslationMatrix_YComponent[_approachTile]; + int _approachX + = _approachTile - DAT_ViewportRenderState::instance.translationMatrix[_approachY].addXgetTile; + int _approachDistanceX; + if (_approachX * 8 < _microX) { + _approachDistanceX = _microX + _approachX * -8; + } else { + _approachDistanceX = _approachX * 8 - _microX; + } + int _approachDistance; + if (_approachY * 8 < _microY) { + _approachDistance = _microY + _approachY * -8; + } else { + _approachDistance = _approachY * 8 - _microY; + } + if (_approachDistance <= _approachDistanceX) { + _approachDistance = _approachDistanceX; + } + if (_approachDistance < _bestApproachDistance) { + _bestApproachDistance = _approachDistance; + _bestApproachDirection = _direction; + } + } + if (_bestApproachDirection >= 0) { + _bestScore = _score; + _chosenRawDistance = _rawDistance; + _foundEnemyID = _enemyUnitID; + } + } + bool _restoreSavedDestination = false; + if (_stanceBasedRange == 0) { + if (this->units[unitID].lookForEnemy == 0) { + this->units[unitID].movementType_OR_targetUnitID = 0; + if (this->units[unitID].state.generic == OpenSHC::Map::Units::States::US_MOVE_TO_DESTINATION) { + _restoreSavedDestination = true; + } + } + } else if (this->units[unitID].lookForEnemy >= 0) { + if (_skipStanceSearch) { + if (this->units[unitID].lookForEnemy == 0) { + this->units[unitID].movementType_OR_targetUnitID = 0; + if (this->units[unitID].state.generic == OpenSHC::Map::Units::States::US_MOVE_TO_DESTINATION) { + _restoreSavedDestination = true; + } + } + } else { + bool _headedToEnemy = false; + if (_foundEnemyID != 0 + && MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func:: + calculateCanPlayerUnitsNavigateToAreaFromArea, + DAT_PathFindingState::ptr)(this->units[unitID].owner, (short)_area, + (short)DAT_TileMapState::instance.PathConnectionLayer[this->units[_foundEnemyID].tile], + this->units[unitID].unitCanClimb) + != 0) { + this->units[unitID].state.generic = OpenSHC::Map::Units::States::US_MOVE_TO_DESTINATION; + this->units[unitID].animationCycleNumber = 0; + if (this->units[unitID]._someX_2 == 0) { + this->units[unitID]._someX_2 = this->units[unitID].destinationX_2Unk; + this->units[unitID]._someY_2 = this->units[unitID].destinationY_2Unk; + } + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::findNearestValidDigTileNearTarget, + DAT_TileMapState::ptr)(this->units[unitID].x, this->units[unitID].y, + this->units[_foundEnemyID].x, this->units[_foundEnemyID].y); + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::setDestinationForUnit, this)(unitID, + DAT_TileMapState::instance.field155_0x5549a8, DAT_TileMapState::instance.field156_0x5549ac, + 0); + int _lookAhead = -0x1e - _chosenRawDistance; + this->units[unitID].moveDelay = 0; + if (_lookAhead > -0x33) { + _lookAhead = -0x32; + } + this->units[unitID].lookForEnemy = (short)_lookAhead; + if (this->units[unitID].movementType_OR_targetUnitID != _foundEnemyID) { + this->units[unitID].movementType_OR_targetUnitID = (short)_foundEnemyID; + this->units[_foundEnemyID].huntedBy = this->units[_foundEnemyID].huntedBy + 1; + } + _headedToEnemy = true; + } + if (!_headedToEnemy) { + this->units[unitID].lookForEnemy = -8; + this->units[unitID].movementType_OR_targetUnitID = 0; + _restoreSavedDestination = true; + } + } + } + if (_restoreSavedDestination && this->units[unitID]._someX_2 != 0) { + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::setDestinationForUnit, this)( + unitID, this->units[unitID]._someX_2, this->units[unitID]._someY_2, 0); + this->units[unitID].moveDelay = 0; + this->units[unitID]._someY_2 = 0; + this->units[unitID]._someX_2 = 0; + this->units[unitID].state.generic = OpenSHC::Map::Units::States::US_MOVE_TO_DESTINATION; + } + if ((int)_minDistance > 32000) { + _minDistance = 32000; + } + return _minDistance; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index aada8f7b1..2e4fdf8b5 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -61409,7 +61409,7 @@ SHC_3BB0A8C1_0x00549C70 | 0.0% | Pending SHC_3BB0A8C1_0x0054A770 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x0054A7B0 | 0.0% | Pending +SHC_3BB0A8C1_0x0054A7B0 | 34.0% | orig walks enemy array ptr SHC_3BB0A8C1_0x0054AA40 | 0.0% | Pending From c6849617ee1ce990973237212fef6573e547d16a Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 10:16:41 +0200 Subject: [PATCH 186/299] reimplement: SHC_3BB0A8C1_0x0053A5B0 9.88% reg alloc differs --- .../UnitsState/renderDebugDataUnitData.cpp | 231 ++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 232 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/renderDebugDataUnitData.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/renderDebugDataUnitData.cpp b/src/OpenSHC/Map/Units/UnitsState/renderDebugDataUnitData.cpp new file mode 100644 index 000000000..41ce549f6 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/renderDebugDataUnitData.cpp @@ -0,0 +1,231 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Text/TextManager.func.hpp" +#include "OpenSHC/Text/TextAlignment.hpp" +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +#include "OpenSHC/Globals/DAT_EntityState.hpp" +#include "OpenSHC/Globals/DAT_GameState.hpp" +#include "OpenSHC/Globals/DAT_PathFindingState.hpp" +#include "OpenSHC/Globals/DAT_TextManagerObject.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Text::TextAlignment; + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x0053A5B0 + void UnitsState::renderDebugDataUnitData(int x, int y, int width, int height) + + { + int _selectedUnitID = this->lastSelectedUnitID; + int _ownerID = this->units[this->lastSelectedUnitID].owner; + short _tribeID = this->units[this->lastSelectedUnitID].tribeID; + int _lineY = 0; + int _column0 = x + 2; + if (this->lastSelectedUnitID < 1) { + MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( + "Not watching a chimp ", _column0, y, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, FALSE, 0); + _lineY = y + 0xe; + MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( + "Total chimps: ", _column0, _lineY, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, FALSE, 0); + MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( + this->unitCount, _column0, _lineY, OpenSHC::Text::TTA_LEFT, 0x80ff, 0x12, TRUE, 0); + MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( + "Total flies: ", x + 0x20, _lineY, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, TRUE, 0); + MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( + DAT_EntityState::instance.totalEntityCount, x + 0x20, _lineY, OpenSHC::Text::TTA_LEFT, 0x80ff, 0x12, + TRUE, 0); + _lineY = y + 0x1c; + MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( + "No of teleports: ", _column0, _lineY, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, FALSE, 0); + MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( + DAT_PathFindingState::instance.numberOfClimbTeleports, _column0, _lineY, OpenSHC::Text::TTA_LEFT, + 0x80ff, 0x12, TRUE, 0); + MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( + "greatest loading: ", x + 0x7a, _lineY, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, FALSE, 0); + MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( + DAT_PathFindingState::instance.debugGreatestClimbLoading, x + 0x7a, _lineY, OpenSHC::Text::TTA_LEFT, + 0x80ff, 0x12, TRUE, 0); + MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( + "total zones: ", _column0, y + 0x2a, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, FALSE, 0); + MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( + DAT_PathFindingState::instance.totalZones, _column0, y + 0x2a, OpenSHC::Text::TTA_LEFT, 0x80ff, + 0x12, TRUE, 0); + MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( + "Lost chimps: ", _column0, y + 0x54, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, FALSE, 0); + MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( + this->lostChimps, _column0, y + 0x54, OpenSHC::Text::TTA_LEFT, 0x80ff, 0x12, TRUE, 0); + } + MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( + "Watching chimp: ", _column0, y, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, FALSE, 0); + MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( + _selectedUnitID, _column0, y, OpenSHC::Text::TTA_LEFT, 0x80ff, 0x12, TRUE, 0); + int _column1 = x + 0x20; + MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( + "type: ", _column1, y, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, TRUE, 0); + MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( + (int)(short)this->units[_selectedUnitID].unitType, _column1, y, OpenSHC::Text::TTA_LEFT, 0x80ff, 0x12, + TRUE, 0); + int _column2 = x + 0x3e; + MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( + "player: ", _column2, y, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, TRUE, 0); + MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( + _lineY, _column2, y, OpenSHC::Text::TTA_LEFT, 0x80ff, 0x12, TRUE, 0); + int _column3 = x + 0x5c; + MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( + "status: ", _column3, y, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, TRUE, 0); + MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( + (int)(short)this->units[_selectedUnitID].logicalState, _column3, y, OpenSHC::Text::TTA_LEFT, 0x80ff, + 0x12, TRUE, 0); + MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( + "dying: ", _column0, y + 0xe, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, FALSE, 0); + MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( + (int)this->units[_selectedUnitID].dying, _column0, y + 0xe, OpenSHC::Text::TTA_LEFT, 0x80ff, 0x12, TRUE, + 0); + MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( + "next_chimp: ", _column1, y + 0xe, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, TRUE, 0); + MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( + (int)(short)this->units[_selectedUnitID].nextUnitOnTheSameTile, _column1, y + 0xe, + OpenSHC::Text::TTA_LEFT, 0x80ff, 0x12, TRUE, 0); + MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( + "using teleport: ", _column2, y + 0xe, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, TRUE, 0); + MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( + (int)this->units[_selectedUnitID].usingTeleport, _column2, y + 0xe, OpenSHC::Text::TTA_LEFT, 0x80ff, + 0x12, TRUE, 0); + MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( + "elbowed: ", _column3, y + 0xe, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, TRUE, 0); + MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( + (int)this->units[_selectedUnitID].unitOrderWhenOnSameTile, _column3, y + 0xe, OpenSHC::Text::TTA_LEFT, + 0x80ff, 0x12, TRUE, 0); + int _column4 = x + 0x7a; + MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( + "sloth: ", _column4, y + 0xe, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, TRUE, 0); + MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( + (int)this->units[_selectedUnitID].moveDelay, _column4, y + 0xe, OpenSHC::Text::TTA_LEFT, 0x80ff, 0x12, + TRUE, 0); + MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( + "enemyD ", _column0, y + 0x1c, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, FALSE, 0); + MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( + (int)this->units[_selectedUnitID].closestEnemyMicroDistance, _column0, y + 0x1c, + OpenSHC::Text::TTA_LEFT, 0x80ff, 0x12, TRUE, 0); + MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( + "enemies ", _column1, y + 0x1c, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, TRUE, 0); + MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( + DAT_GameState::instance.playerDataArray[_lineY].enemies, _column1, y + 0x1c, OpenSHC::Text::TTA_LEFT, + 0x80ff, 0x12, TRUE, 0); + MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( + "facing ", _column2, y + 0x1c, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, TRUE, 0); + MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( + (int)this->units[_selectedUnitID].facingDirection, _column2, y + 0x1c, OpenSHC::Text::TTA_LEFT, 0x80ff, + 0x12, TRUE, 0); + MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( + "jump ", _column3, y + 0x1c, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, TRUE, 0); + MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( + (int)this->units[_selectedUnitID].buildingHeight, _column3, y + 0x1c, OpenSHC::Text::TTA_LEFT, 0x80ff, + 0x12, TRUE, 0); + MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( + "z ", _column4, y + 0x1c, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, TRUE, 0); + MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( + (int)this->units[_selectedUnitID].terrainOrClimbHeight, _column4, y + 0x1c, OpenSHC::Text::TTA_LEFT, + 0x80ff, 0x12, TRUE, 0); + MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( + "ai_status ", _column0, y + 0x2a, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, FALSE, 0); + MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( + (int)(short)this->units[_selectedUnitID].state.generic, _column0, y + 0x2a, OpenSHC::Text::TTA_LEFT, + 0x80ff, 0x12, TRUE, 0); + MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( + "anim_frame_no ", _column1, y + 0x2a, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, TRUE, 0); + MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( + this->units[_selectedUnitID].animationCycleNumber, _column1, y + 0x2a, OpenSHC::Text::TTA_LEFT, 0x80ff, + 0x12, TRUE, 0); + MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( + "gfx_no ", _column2, y + 0x2a, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, TRUE, 0); + MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( + this->units[_selectedUnitID].gfxNumber, _column2, y + 0x2a, OpenSHC::Text::TTA_LEFT, 0x80ff, 0x12, TRUE, + 0); + MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( + "Look 4 enemy ", _column0, y + 0x38, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, FALSE, 0); + MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( + (int)this->units[_selectedUnitID].lookForEnemy, _column0, y + 0x38, OpenSHC::Text::TTA_LEFT, 0x80ff, + 0x12, TRUE, 0); + MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( + "Attacked By ", _column1, y + 0x38, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, TRUE, 0); + MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( + (int)this->units[_selectedUnitID].attackedBy, _column1, y + 0x38, OpenSHC::Text::TTA_LEFT, 0x80ff, 0x12, + TRUE, 0); + MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( + "Hps ", _column2, y + 0x38, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, TRUE, 0); + MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( + this->units[_selectedUnitID].health, _column2, y + 0x38, OpenSHC::Text::TTA_LEFT, 0x80ff, 0x12, TRUE, + 0); + MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( + "Hunted By ", _column3, y + 0x38, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, TRUE, 0); + MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( + (int)this->units[_selectedUnitID].huntedBy, _column3, y + 0x38, OpenSHC::Text::TTA_LEFT, 0x80ff, 0x12, + TRUE, 0); + MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( + "target type ", _column0, y + 0x46, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, FALSE, 0); + MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( + (int)(short)this->units[_selectedUnitID].targetingType, _column0, y + 0x46, OpenSHC::Text::TTA_LEFT, + 0x80ff, 0x12, TRUE, 0); + MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( + "seated ", _column1, y + 0x46, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, TRUE, 0); + MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( + (int)this->units[_selectedUnitID].seated, _column1, y + 0x46, OpenSHC::Text::TTA_LEFT, 0x80ff, 0x12, + TRUE, 0); + MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( + "vanish ", _column2, y + 0x46, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, TRUE, 0); + MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( + this->units[_selectedUnitID].vanish, _column2, y + 0x46, OpenSHC::Text::TTA_LEFT, 0x80ff, 0x12, TRUE, + 0); + MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( + "was on stone gate ", _column3, y + 0x46, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, TRUE, 0); + MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( + (int)(char)this->units[_selectedUnitID].wasOnStoneGate, _column3, y + 0x46, OpenSHC::Text::TTA_LEFT, + 0x80ff, 0x12, TRUE, 0); + MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( + "Idle ", _column0, y + 0x54, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, FALSE, 0); + MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( + (int)this->units[_selectedUnitID].idle, _column0, y + 0x54, OpenSHC::Text::TTA_LEFT, 0x80ff, 0x12, TRUE, + 0); + MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( + "Target ", _column1, y + 0x54, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, TRUE, 0); + MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( + (int)this->units[_selectedUnitID].target, _column1, y + 0x54, OpenSHC::Text::TTA_LEFT, 0x80ff, 0x12, + TRUE, 0); + MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( + "Banked ", _column2, y + 0x54, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, TRUE, 0); + MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( + (int)this->units[_selectedUnitID].banked, _column2, y + 0x54, OpenSHC::Text::TTA_LEFT, 0x80ff, 0x12, + TRUE, 0); + _lineY = y + 0x62; + MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( + "Working ", _column0, _lineY, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, FALSE, 0); + MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( + *(int*)(this->units[_selectedUnitID].manningEngineerRef + this->units[_selectedUnitID].working * 2 + + -0x16), + _column0, _lineY, OpenSHC::Text::TTA_LEFT, (uint)((int)(33023)), 0x12, TRUE, 0); + MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( + "Av ", _column1, _lineY, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, TRUE, 0); + MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( + this->units[_selectedUnitID].av, _column1, _lineY, OpenSHC::Text::TTA_LEFT, 0x80ff, 0x12, TRUE, 0); + MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( + "Bless ", _column2, _lineY, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, TRUE, 0); + MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( + this->units[_selectedUnitID].blessedAmount, _column2, _lineY, OpenSHC::Text::TTA_LEFT, 0x80ff, 0x12, + TRUE, 0); + MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( + "Tribe ", _column3, _lineY, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, TRUE, 0); + MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( + (int)_tribeID, _column3, _lineY, OpenSHC::Text::TTA_LEFT, 0x80ff, 0x12, TRUE, 0); + MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( + "SA ", _column4, _lineY, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, TRUE, 0); + MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( + (int)this->units[_selectedUnitID].SA, _column4, _lineY, OpenSHC::Text::TTA_LEFT, 0x80ff, 0x12, TRUE, 0); + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 2e4fdf8b5..12c1b0ff1 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -59617,7 +59617,7 @@ SHC_3BB0A8C1_0x0053A4D0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0053A560 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x0053A5B0 | 0.0% | Pending +SHC_3BB0A8C1_0x0053A5B0 | 9.9% | reg alloc differs SHC_3BB0A8C1_0x0053B1F0 | 0.0% | Pending From c1e88d0fc76b45c9c1d477cf3aae0a70edd7ccc9 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 10:18:37 +0200 Subject: [PATCH 187/299] reimplement: SHC_3BB0A8C1_0x0053A5B0 9.88% reg alloc differs --- .../UnitsState/renderDebugDataUnitData.cpp | 88 ++++++++++--------- 1 file changed, 48 insertions(+), 40 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/renderDebugDataUnitData.cpp b/src/OpenSHC/Map/Units/UnitsState/renderDebugDataUnitData.cpp index 41ce549f6..17831f805 100644 --- a/src/OpenSHC/Map/Units/UnitsState/renderDebugDataUnitData.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/renderDebugDataUnitData.cpp @@ -2,6 +2,7 @@ #include "OpenSHC/Text/TextManager.func.hpp" #include "OpenSHC/Text/TextAlignment.hpp" #include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" +#include "OpenSHC/string-literals.hpp" #include "OpenSHC/Globals/DAT_EntityState.hpp" #include "OpenSHC/Globals/DAT_GameState.hpp" @@ -26,202 +27,209 @@ namespace Map { int _column0 = x + 2; if (this->lastSelectedUnitID < 1) { MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( - "Not watching a chimp ", _column0, y, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, FALSE, 0); + (char*)s_Not_watching_a_chimp_005abde0, _column0, y, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, FALSE, + 0); _lineY = y + 0xe; MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( - "Total chimps: ", _column0, _lineY, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, FALSE, 0); + (char*)s_Total_chimps__005abdd0, _column0, _lineY, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, FALSE, + 0); MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( this->unitCount, _column0, _lineY, OpenSHC::Text::TTA_LEFT, 0x80ff, 0x12, TRUE, 0); MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( - "Total flies: ", x + 0x20, _lineY, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, TRUE, 0); + (char*)s_Total_flies__005abdc0, x + 0x20, _lineY, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, TRUE, 0); MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( DAT_EntityState::instance.totalEntityCount, x + 0x20, _lineY, OpenSHC::Text::TTA_LEFT, 0x80ff, 0x12, TRUE, 0); _lineY = y + 0x1c; MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( - "No of teleports: ", _column0, _lineY, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, FALSE, 0); + (char*)s_No_of_teleports__005abdac, _column0, _lineY, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, + FALSE, 0); MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( DAT_PathFindingState::instance.numberOfClimbTeleports, _column0, _lineY, OpenSHC::Text::TTA_LEFT, 0x80ff, 0x12, TRUE, 0); MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( - "greatest loading: ", x + 0x7a, _lineY, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, FALSE, 0); + (char*)s_greatest_loading__005abd98, x + 0x7a, _lineY, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, + FALSE, 0); MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( DAT_PathFindingState::instance.debugGreatestClimbLoading, x + 0x7a, _lineY, OpenSHC::Text::TTA_LEFT, 0x80ff, 0x12, TRUE, 0); MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( - "total zones: ", _column0, y + 0x2a, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, FALSE, 0); + (char*)s_total_zones__005abd88, _column0, y + 0x2a, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, FALSE, + 0); MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( DAT_PathFindingState::instance.totalZones, _column0, y + 0x2a, OpenSHC::Text::TTA_LEFT, 0x80ff, 0x12, TRUE, 0); MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( - "Lost chimps: ", _column0, y + 0x54, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, FALSE, 0); + (char*)s_Lost_chimps__005abd78, _column0, y + 0x54, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, FALSE, + 0); MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( this->lostChimps, _column0, y + 0x54, OpenSHC::Text::TTA_LEFT, 0x80ff, 0x12, TRUE, 0); } MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( - "Watching chimp: ", _column0, y, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, FALSE, 0); + (char*)s_Watching_chimp__005abd64, _column0, y, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, FALSE, 0); MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( _selectedUnitID, _column0, y, OpenSHC::Text::TTA_LEFT, 0x80ff, 0x12, TRUE, 0); int _column1 = x + 0x20; MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( - "type: ", _column1, y, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, TRUE, 0); + (char*)s_type__005abd5c, _column1, y, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, TRUE, 0); MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( (int)(short)this->units[_selectedUnitID].unitType, _column1, y, OpenSHC::Text::TTA_LEFT, 0x80ff, 0x12, TRUE, 0); int _column2 = x + 0x3e; MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( - "player: ", _column2, y, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, TRUE, 0); + (char*)s_player__005abd50, _column2, y, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, TRUE, 0); MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( _lineY, _column2, y, OpenSHC::Text::TTA_LEFT, 0x80ff, 0x12, TRUE, 0); int _column3 = x + 0x5c; MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( - "status: ", _column3, y, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, TRUE, 0); + (char*)s_status__005abd44, _column3, y, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, TRUE, 0); MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( (int)(short)this->units[_selectedUnitID].logicalState, _column3, y, OpenSHC::Text::TTA_LEFT, 0x80ff, 0x12, TRUE, 0); MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( - "dying: ", _column0, y + 0xe, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, FALSE, 0); + (char*)s_dying__005abd3c, _column0, y + 0xe, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, FALSE, 0); MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( (int)this->units[_selectedUnitID].dying, _column0, y + 0xe, OpenSHC::Text::TTA_LEFT, 0x80ff, 0x12, TRUE, 0); MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( - "next_chimp: ", _column1, y + 0xe, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, TRUE, 0); + (char*)s_next_chimp__005abd2c, _column1, y + 0xe, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, TRUE, 0); MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( (int)(short)this->units[_selectedUnitID].nextUnitOnTheSameTile, _column1, y + 0xe, OpenSHC::Text::TTA_LEFT, 0x80ff, 0x12, TRUE, 0); MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( - "using teleport: ", _column2, y + 0xe, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, TRUE, 0); + (char*)s_using_teleport__005abd18, _column2, y + 0xe, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, TRUE, 0); MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( (int)this->units[_selectedUnitID].usingTeleport, _column2, y + 0xe, OpenSHC::Text::TTA_LEFT, 0x80ff, 0x12, TRUE, 0); MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( - "elbowed: ", _column3, y + 0xe, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, TRUE, 0); + (char*)s_elbowed__005abd0c, _column3, y + 0xe, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, TRUE, 0); MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( (int)this->units[_selectedUnitID].unitOrderWhenOnSameTile, _column3, y + 0xe, OpenSHC::Text::TTA_LEFT, 0x80ff, 0x12, TRUE, 0); int _column4 = x + 0x7a; MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( - "sloth: ", _column4, y + 0xe, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, TRUE, 0); + (char*)s_sloth__005abd04, _column4, y + 0xe, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, TRUE, 0); MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( (int)this->units[_selectedUnitID].moveDelay, _column4, y + 0xe, OpenSHC::Text::TTA_LEFT, 0x80ff, 0x12, TRUE, 0); MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( - "enemyD ", _column0, y + 0x1c, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, FALSE, 0); + (char*)s_enemyD_005abcfc, _column0, y + 0x1c, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, FALSE, 0); MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( (int)this->units[_selectedUnitID].closestEnemyMicroDistance, _column0, y + 0x1c, OpenSHC::Text::TTA_LEFT, 0x80ff, 0x12, TRUE, 0); MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( - "enemies ", _column1, y + 0x1c, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, TRUE, 0); + (char*)s_enemies_005a51f4, _column1, y + 0x1c, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, TRUE, 0); MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( DAT_GameState::instance.playerDataArray[_lineY].enemies, _column1, y + 0x1c, OpenSHC::Text::TTA_LEFT, 0x80ff, 0x12, TRUE, 0); MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( - "facing ", _column2, y + 0x1c, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, TRUE, 0); + (char*)s_facing_005abcf4, _column2, y + 0x1c, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, TRUE, 0); MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( (int)this->units[_selectedUnitID].facingDirection, _column2, y + 0x1c, OpenSHC::Text::TTA_LEFT, 0x80ff, 0x12, TRUE, 0); MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( - "jump ", _column3, y + 0x1c, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, TRUE, 0); + (char*)s_jump_005abcec, _column3, y + 0x1c, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, TRUE, 0); MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( (int)this->units[_selectedUnitID].buildingHeight, _column3, y + 0x1c, OpenSHC::Text::TTA_LEFT, 0x80ff, 0x12, TRUE, 0); MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( - "z ", _column4, y + 0x1c, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, TRUE, 0); + (char*)s_z_005abce8, _column4, y + 0x1c, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, TRUE, 0); MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( (int)this->units[_selectedUnitID].terrainOrClimbHeight, _column4, y + 0x1c, OpenSHC::Text::TTA_LEFT, 0x80ff, 0x12, TRUE, 0); MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( - "ai_status ", _column0, y + 0x2a, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, FALSE, 0); + (char*)s_ai_status_005abcdc, _column0, y + 0x2a, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, FALSE, 0); MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( (int)(short)this->units[_selectedUnitID].state.generic, _column0, y + 0x2a, OpenSHC::Text::TTA_LEFT, 0x80ff, 0x12, TRUE, 0); MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( - "anim_frame_no ", _column1, y + 0x2a, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, TRUE, 0); + (char*)s_anim_frame_no_005abccc, _column1, y + 0x2a, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, TRUE, 0); MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( this->units[_selectedUnitID].animationCycleNumber, _column1, y + 0x2a, OpenSHC::Text::TTA_LEFT, 0x80ff, 0x12, TRUE, 0); MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( - "gfx_no ", _column2, y + 0x2a, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, TRUE, 0); + (char*)s_gfx_no_005abcc4, _column2, y + 0x2a, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, TRUE, 0); MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( this->units[_selectedUnitID].gfxNumber, _column2, y + 0x2a, OpenSHC::Text::TTA_LEFT, 0x80ff, 0x12, TRUE, 0); MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( - "Look 4 enemy ", _column0, y + 0x38, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, FALSE, 0); + (char*)s_Look_4_enemy_005abcb4, _column0, y + 0x38, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, FALSE, 0); MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( (int)this->units[_selectedUnitID].lookForEnemy, _column0, y + 0x38, OpenSHC::Text::TTA_LEFT, 0x80ff, 0x12, TRUE, 0); MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( - "Attacked By ", _column1, y + 0x38, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, TRUE, 0); + (char*)s_Attacked_By_005abca4, _column1, y + 0x38, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, TRUE, 0); MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( (int)this->units[_selectedUnitID].attackedBy, _column1, y + 0x38, OpenSHC::Text::TTA_LEFT, 0x80ff, 0x12, TRUE, 0); MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( - "Hps ", _column2, y + 0x38, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, TRUE, 0); + (char*)s_Hps_005abc9c, _column2, y + 0x38, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, TRUE, 0); MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( this->units[_selectedUnitID].health, _column2, y + 0x38, OpenSHC::Text::TTA_LEFT, 0x80ff, 0x12, TRUE, 0); MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( - "Hunted By ", _column3, y + 0x38, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, TRUE, 0); + (char*)s_Hunted_By_005abc90, _column3, y + 0x38, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, TRUE, 0); MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( (int)this->units[_selectedUnitID].huntedBy, _column3, y + 0x38, OpenSHC::Text::TTA_LEFT, 0x80ff, 0x12, TRUE, 0); MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( - "target type ", _column0, y + 0x46, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, FALSE, 0); + (char*)s_target_type_005abc80, _column0, y + 0x46, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, FALSE, 0); MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( (int)(short)this->units[_selectedUnitID].targetingType, _column0, y + 0x46, OpenSHC::Text::TTA_LEFT, 0x80ff, 0x12, TRUE, 0); MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( - "seated ", _column1, y + 0x46, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, TRUE, 0); + (char*)s_seated_005abc78, _column1, y + 0x46, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, TRUE, 0); MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( (int)this->units[_selectedUnitID].seated, _column1, y + 0x46, OpenSHC::Text::TTA_LEFT, 0x80ff, 0x12, TRUE, 0); MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( - "vanish ", _column2, y + 0x46, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, TRUE, 0); + (char*)s_vanish_005abc70, _column2, y + 0x46, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, TRUE, 0); MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( this->units[_selectedUnitID].vanish, _column2, y + 0x46, OpenSHC::Text::TTA_LEFT, 0x80ff, 0x12, TRUE, 0); MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( - "was on stone gate ", _column3, y + 0x46, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, TRUE, 0); + (char*)s_was_on_stone_gate_005abc5c, _column3, y + 0x46, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, TRUE, + 0); MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( (int)(char)this->units[_selectedUnitID].wasOnStoneGate, _column3, y + 0x46, OpenSHC::Text::TTA_LEFT, 0x80ff, 0x12, TRUE, 0); MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( - "Idle ", _column0, y + 0x54, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, FALSE, 0); + (char*)s_Idle_005abc54, _column0, y + 0x54, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, FALSE, 0); MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( (int)this->units[_selectedUnitID].idle, _column0, y + 0x54, OpenSHC::Text::TTA_LEFT, 0x80ff, 0x12, TRUE, 0); MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( - "Target ", _column1, y + 0x54, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, TRUE, 0); + (char*)s_Target_005abc4c, _column1, y + 0x54, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, TRUE, 0); MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( (int)this->units[_selectedUnitID].target, _column1, y + 0x54, OpenSHC::Text::TTA_LEFT, 0x80ff, 0x12, TRUE, 0); MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( - "Banked ", _column2, y + 0x54, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, TRUE, 0); + (char*)s_Banked_005abc44, _column2, y + 0x54, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, TRUE, 0); MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( (int)this->units[_selectedUnitID].banked, _column2, y + 0x54, OpenSHC::Text::TTA_LEFT, 0x80ff, 0x12, TRUE, 0); _lineY = y + 0x62; MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( - "Working ", _column0, _lineY, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, FALSE, 0); + (char*)s_Working_005abc38, _column0, _lineY, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, FALSE, 0); MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( *(int*)(this->units[_selectedUnitID].manningEngineerRef + this->units[_selectedUnitID].working * 2 + -0x16), _column0, _lineY, OpenSHC::Text::TTA_LEFT, (uint)((int)(33023)), 0x12, TRUE, 0); MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( - "Av ", _column1, _lineY, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, TRUE, 0); + (char*)s_Av_005abc34, _column1, _lineY, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, TRUE, 0); MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( this->units[_selectedUnitID].av, _column1, _lineY, OpenSHC::Text::TTA_LEFT, 0x80ff, 0x12, TRUE, 0); MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( - "Bless ", _column2, _lineY, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, TRUE, 0); + (char*)s_Bless_005abc2c, _column2, _lineY, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, TRUE, 0); MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( this->units[_selectedUnitID].blessedAmount, _column2, _lineY, OpenSHC::Text::TTA_LEFT, 0x80ff, 0x12, TRUE, 0); MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( - "Tribe ", _column3, _lineY, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, TRUE, 0); + (char*)s_Tribe_005abc24, _column3, _lineY, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, TRUE, 0); MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( (int)_tribeID, _column3, _lineY, OpenSHC::Text::TTA_LEFT, 0x80ff, 0x12, TRUE, 0); MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( - "SA ", _column4, _lineY, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, TRUE, 0); + (char*)s_SA_005abc20, _column4, _lineY, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, TRUE, 0); MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( (int)this->units[_selectedUnitID].SA, _column4, _lineY, OpenSHC::Text::TTA_LEFT, 0x80ff, 0x12, TRUE, 0); } From fd1ef5bdfa4273ba3dcf5412c901d5ad50fc4a79 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 10:19:24 +0200 Subject: [PATCH 188/299] reimplement: SHC_3BB0A8C1_0x0053A5B0 9.80% reg alloc differs --- .../Map/Units/UnitsState/renderDebugDataUnitData.cpp | 6 +++--- status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/renderDebugDataUnitData.cpp b/src/OpenSHC/Map/Units/UnitsState/renderDebugDataUnitData.cpp index 17831f805..853e038b2 100644 --- a/src/OpenSHC/Map/Units/UnitsState/renderDebugDataUnitData.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/renderDebugDataUnitData.cpp @@ -21,11 +21,11 @@ namespace Map { { int _selectedUnitID = this->lastSelectedUnitID; - int _ownerID = this->units[this->lastSelectedUnitID].owner; - short _tribeID = this->units[this->lastSelectedUnitID].tribeID; + int _ownerID = this->units[_selectedUnitID].owner; + short _tribeID = this->units[_selectedUnitID].tribeID; int _lineY = 0; int _column0 = x + 2; - if (this->lastSelectedUnitID < 1) { + if (_selectedUnitID < 1) { MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( (char*)s_Not_watching_a_chimp_005abde0, _column0, y, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, FALSE, 0); diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 12c1b0ff1..4a9f067ca 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -59617,7 +59617,7 @@ SHC_3BB0A8C1_0x0053A4D0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0053A560 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x0053A5B0 | 9.9% | reg alloc differs +SHC_3BB0A8C1_0x0053A5B0 | 9.8% | reg alloc differs SHC_3BB0A8C1_0x0053B1F0 | 0.0% | Pending From 9d2a3c36a7f841e2f4f50a2c9d222a377e956d7f Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 10:20:18 +0200 Subject: [PATCH 189/299] reimplement: SHC_3BB0A8C1_0x0053A5B0 9.81% reg alloc, this on stack --- src/OpenSHC/Map/Units/UnitsState/renderDebugDataUnitData.cpp | 2 +- status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/renderDebugDataUnitData.cpp b/src/OpenSHC/Map/Units/UnitsState/renderDebugDataUnitData.cpp index 853e038b2..59d6b1a36 100644 --- a/src/OpenSHC/Map/Units/UnitsState/renderDebugDataUnitData.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/renderDebugDataUnitData.cpp @@ -23,7 +23,7 @@ namespace Map { int _selectedUnitID = this->lastSelectedUnitID; int _ownerID = this->units[_selectedUnitID].owner; short _tribeID = this->units[_selectedUnitID].tribeID; - int _lineY = 0; + int _lineY; int _column0 = x + 2; if (_selectedUnitID < 1) { MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 4a9f067ca..cd098396a 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -59617,7 +59617,7 @@ SHC_3BB0A8C1_0x0053A4D0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0053A560 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x0053A5B0 | 9.8% | reg alloc differs +SHC_3BB0A8C1_0x0053A5B0 | 9.8% | reg alloc, this on stack SHC_3BB0A8C1_0x0053B1F0 | 0.0% | Pending From dc7faf4f96a8356c8038ab3cb2d67a6812e78e6a Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 10:24:56 +0200 Subject: [PATCH 190/299] reimplement: SHC_3BB0A8C1_0x00537F60 62.54% jump table order differs --- ...tUnitStateTextParameterAndResourceType.cpp | 920 ++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 921 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/getUnitStateTextParameterAndResourceType.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/getUnitStateTextParameterAndResourceType.cpp b/src/OpenSHC/Map/Units/UnitsState/getUnitStateTextParameterAndResourceType.cpp new file mode 100644 index 000000000..1fb9dd000 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/getUnitStateTextParameterAndResourceType.cpp @@ -0,0 +1,920 @@ +#include "OpenSHC/Map/Buildings/BuildingsState.func.hpp" +#include "OpenSHC/Map/Units.func.hpp" +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Game/Resources/ResourceType.hpp" +#include "OpenSHC/Map/Buildings/BuildingType.hpp" +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_GameState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Game::Resources::ResourceType; + using OpenSHC::Map::Buildings::BuildingType; + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x00537F60 + int UnitsState::getUnitStateTextParameterAndResourceType(int unitIndex, ResourceType* pResourceType) + + { + int _state = (short)this->units[unitIndex].state.generic; + *pResourceType = (ResourceType)0; + if (this->units[unitIndex].dying != 0) { + /* + "Dying" + */ + + return 0xc; + } + if (_state == 0x79 || MACRO_CALL(OpenSHC::Map::Units_Func::CheckUnitProductionPaused)(unitIndex) != FALSE) { + /* + This is an optimized % 4, producing -3 to 3 + */ + + uint _rng_0x79 = this->units[unitIndex].fixedRng & 0x80000003; + if ((int)_rng_0x79 < 0) { + _rng_0x79 = (_rng_0x79 - 1 | 0xfffffffc) + 1; + } + /* + "Wandering around + Eating fire + (go to goodthing) + Having a rest + Enjoying a break + Taking some time off + Wandering randomly" + */ + + return (int)(_rng_0x79 + 0x5f); + } + if (_state == 0x6a) { + /* + "Fighting" + */ + + return 0x73; + } + switch (this->units[unitIndex].unitType) { + case OpenSHC::Map::Units::UT_PEASANT: + if (_state == 5) { + /* + "Swearing loyalty" + */ + + return 0x26; + } + if (_state == 8) { + /* + "Listening + Waiting for job + Hanging around + Waiting + Talking + Making a speech + Telling a joke + Recounting a story" + */ + + /* + Waiting at campfire + */ + + switch (this->units[unitIndex].substate) { + case 0x6a: + return 0x1e; + case 0x6b: + return 0x1f; + case 0x6e: + return 0x20; + case 0x6f: + return 0x21; + case 0x72: + return 0x22; + case 0x73: + return 0x23; + case 0x74: + return 0x24; + case 0x75: + return 0x25; + } + } + /* + "Waiting for job" + */ + + return 0x1d; + case OpenSHC::Map::Units::UT_BURNINGMAN: + /* + "Burning" + */ + + return 3; + case OpenSHC::Map::Units::UT_WOODCUTTER: + *pResourceType = OpenSHC::Game::Resources::RT_WOOD; + /* + 0x1: Waiting + 0x6b: Going to chop wood + 0x6c: Felling a tree + 0x6d: Chopping a tree + 0x6e: Returning with log + 0x7: Working + 0x7: Working + 0x2: Awaiting store space + 0xa: Taking goods to store + 0x5: Going to workplace + 0x4: Resting + 0x0: (Unit actions) - + 0x8: Attacking + */ + + switch (_state) { + case 0: + return 1; + case 1: + /* + "Going to chop wood" + */ + + return 0x6b; + case 2: + /* + "Felling a tree" + */ + + return 0x6c; + case 3: + /* + "Chopping a tree" + */ + + return 0x6d; + case 4: + /* + "Returning with log" + */ + + return 0x6e; + case 5: + case 6: + return 7; + case 7: + return 2; + case 8: + return 10; + case 9: + return 5; + case 10: + return 4; + default: + return 0; + case 0x6a: + return 8; + } + case OpenSHC::Map::Units::UT_FLETCHER: + *pResourceType = OpenSHC::Game::Resources::RT_WOOD; + switch (_state) { + case 0: + return 1; + case 1: + return 9; + case 2: + return 6; + case 3: + return 5; + case 4: + case 5: + return 7; + case 6: + return 2; + case 7: + *pResourceType = OpenSHC::Game::Resources::RT_BOW; + return 10; + case 8: + if (MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::getStorageBuildingForResourceTypeAndAmount, + DAT_BuildingsState::ptr)(OpenSHC::Game::Resources::RT_WOOD, 1, this->units[unitIndex].owner) + != 0) { + return 4; + } + return 1; + default: + return 0; + case 0x6a: + return 8; + } + case OpenSHC::Map::Units::UT_TUNNELER: + switch (_state) { + case 0: + case 1: + case 4: + case 5: + case 6: + return 1; + case 2: + case 3: + case 8: + case 9: + return 7; + case 7: + return 0xb; + default: + return 0; + case 0x6a: + return 8; + } + case OpenSHC::Map::Units::UT_HUNTER: + *pResourceType = OpenSHC::Game::Resources::RT_MEAT; + /* + 0x1: Waiting + 0x71: Hunting + 0x72: Returning with kill + 0x7: Working + 0x2: Awaiting store space + 0xa: Taking goods to store + 0x5: Going to workplace + 0x4: Resting + 0x70: Stalking prey + 0x73: Fighting + 0x71: Hunting + 0x73: Fighting + 0x0: (Unit actions) - + 0x8: Attacking + */ + + switch (_state) { + case 0: + case 8: + return 1; + case 1: + case 0xb: + return 0x71; + case 2: + return 0x72; + case 3: + return 7; + case 4: + return 2; + case 5: + return 10; + case 6: + return 5; + case 7: + return 4; + case 9: + /* + 115 or 112 + */ + + return (-(uint)(this->units[this->units[unitIndex].shootTargetedUnit].isStalked != 0) & 0xfffffffd) + + 0x73; + case 10: + return (uint)(this->units[this->units[unitIndex].shootTargetedUnit].isStalked == 0) * 2 + 0x71; + default: + return 0; + case 0x6a: + return 8; + } + case OpenSHC::Map::Units::UT_QUARRYMASON: + switch (_state) { + case 0: + return 1; + default: + return 7; + case 2: + return 5; + case 0x6a: + return 8; + } + case OpenSHC::Map::Units::UT_QUARRYWORKER: + *pResourceType = OpenSHC::Game::Resources::RT_STONE; + switch (_state) { + default: + return 7; + case 1: + case 6: + return 1; + case 2: + return 2; + case 3: + return 10; + case 4: + return 5; + case 5: + return 4; + case 0x6a: + return 8; + } + case OpenSHC::Map::Units::UT_QUARRYOX: + *pResourceType = OpenSHC::Game::Resources::RT_STONE; + switch (_state) { + case 1: + return 10; + case 2: + return 1; + case 3: + return 5; + case 4: + return 0x28; + default: + return 0; + case 0x6a: + return 8; + } + case OpenSHC::Map::Units::UT_PITCHMAN: + *pResourceType = OpenSHC::Game::Resources::RT_PARTIALPITCH; + switch (_state) { + case 0: + return 1; + case 1: + return 7; + case 2: + return 2; + case 3: + return 10; + case 4: + return 5; + default: + return 0; + case 0x6a: + return 8; + } + case OpenSHC::Map::Units::UT_WHEATFARMER: + *pResourceType = OpenSHC::Game::Resources::RT_WHEAT; + switch (_state) { + case 0: + case 1: + return 1; + case 2: + return 5; + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + return 7; + case 9: + return 2; + case 10: + return 10; + default: + return 0; + case 0x6a: + return 8; + } + case OpenSHC::Map::Units::UT_HOPSFARMER: + *pResourceType = OpenSHC::Game::Resources::RT_HOPS; + switch (_state) { + case 0: + case 1: + return 1; + case 2: + return 5; + case 3: + case 4: + case 5: + case 6: + return 7; + case 7: + return 2; + case 8: + return 10; + default: + return 0; + case 0x6a: + return 8; + } + case OpenSHC::Map::Units::UT_APPLEFARMER: + *pResourceType = OpenSHC::Game::Resources::RT_APPLE; + switch (_state) { + case 0: + case 1: + return 1; + case 2: + case 3: + case 4: + case 8: + return 7; + case 5: + return 5; + case 6: + return 2; + case 7: + return 10; + default: + return 0; + case 0x6a: + return 8; + } + case OpenSHC::Map::Units::UT_DAIRYFARMER: + *pResourceType = OpenSHC::Game::Resources::RT_CHEESE; + switch (_state) { + case 0: + case 1: + return 1; + case 2: + return 5; + case 3: + return 7; + case 4: + return 2; + case 5: + return 10; + default: + return 0; + case 0x6a: + return 8; + } + case OpenSHC::Map::Units::UT_MILLER: + switch (_state) { + case 0: + case 1: + case 6: + return 1; + case 2: + return 5; + case 3: + return 9; + case 4: + *pResourceType = OpenSHC::Game::Resources::RT_WHEAT; + return 6; + case 5: + return 7; + case 7: + return 2; + case 8: + *pResourceType = OpenSHC::Game::Resources::RT_FLOUR; + return 10; + default: + return 0; + case 0x6a: + return 8; + } + case OpenSHC::Map::Units::UT_BAKER: + *pResourceType = OpenSHC::Game::Resources::RT_BREAD; + switch (_state) { + case 0: + case 1: + return 1; + case 2: + return 5; + default: + return 7; + case 5: + return 2; + case 6: + return 10; + case 7: + *pResourceType = OpenSHC::Game::Resources::RT_FLOUR; + return 9; + case 8: + *pResourceType = OpenSHC::Game::Resources::RT_FLOUR; + return 6; + case 0x6a: + return 8; + } + case OpenSHC::Map::Units::UT_BREWER: + switch (_state) { + case 0: + case 1: + return 1; + case 2: + *pResourceType = OpenSHC::Game::Resources::RT_HOPS; + return 9; + case 3: + *pResourceType = OpenSHC::Game::Resources::RT_HOPS; + return 6; + case 4: + return 5; + default: + return 7; + case 7: + return 2; + case 8: + *pResourceType = OpenSHC::Game::Resources::RT_ALE; + return 10; + case 9: + return 4; + case 0x6a: + return 8; + } + case OpenSHC::Map::Units::UT_POLETURNER: + switch (_state) { + case 0: + case 1: + return 1; + case 2: + *pResourceType = OpenSHC::Game::Resources::RT_WOOD; + return 9; + case 3: + *pResourceType = OpenSHC::Game::Resources::RT_WOOD; + return 6; + case 4: + return 5; + case 5: + case 6: + return 7; + case 7: + return 2; + case 8: + *pResourceType = (ResourceType)(short)DAT_BuildingsState::instance + .buildings[this->units[unitIndex].workplaceBuildingID_1] + .producedItemTypeNext; + return 10; + default: + return 0; + case 0x6a: + return 8; + } + case OpenSHC::Map::Units::UT_SMITH: + switch (_state) { + case 0: + case 1: + return 1; + case 2: + *pResourceType = OpenSHC::Game::Resources::RT_IRON; + return 9; + case 3: + *pResourceType = OpenSHC::Game::Resources::RT_IRON; + return 6; + case 4: + return 5; + case 5: + case 6: + return 7; + case 7: + return 2; + case 8: + *pResourceType = (ResourceType)(short)DAT_BuildingsState::instance + .buildings[this->units[unitIndex].workplaceBuildingID_1] + .producedItemTypeNext; + return 10; + case 9: + if (MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::getStorageBuildingForResourceTypeAndAmount, + DAT_BuildingsState::ptr)(OpenSHC::Game::Resources::RT_IRON, 1, this->units[unitIndex].owner) + != 0) { + return 4; + } + return 1; + default: + return 0; + case 0x6a: + return 8; + } + case OpenSHC::Map::Units::UT_ARMORER: + switch (_state) { + case 0: + case 1: + return 1; + case 2: + *pResourceType = OpenSHC::Game::Resources::RT_IRON; + return 9; + case 3: + *pResourceType = OpenSHC::Game::Resources::RT_IRON; + return 6; + case 4: + return 5; + case 5: + case 6: + return 7; + case 7: + return 2; + case 8: + *pResourceType = OpenSHC::Game::Resources::RT_IRONARMOR; + return 10; + case 9: + if (MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::getStorageBuildingForResourceTypeAndAmount, + DAT_BuildingsState::ptr)(OpenSHC::Game::Resources::RT_IRON, 1, this->units[unitIndex].owner) + != 0) { + return 4; + } + return 1; + default: + return 0; + case 0x6a: + return 8; + } + case OpenSHC::Map::Units::UT_TANNER: + switch (_state) { + case 0: + case 1: + return 1; + case 2: + return 0x68; + case 3: + return 0x69; + case 4: + return 5; + default: + return 7; + case 7: + return 2; + case 8: + *pResourceType = OpenSHC::Game::Resources::RT_LEATHERARMOR; + return 10; + case 0x6a: + return 8; + } + default: + return 0; + case OpenSHC::Map::Units::UT_MINER: + if (_state == 1) { + return 7; + } + case OpenSHC::Map::Units::UT_TRANSPORTMINER: + switch (_state) { + case 0: + case 1: + case 5: + return 1; + case 2: + return 5; + case 3: + return 2; + case 4: + return 10; + default: + return 7; + case 0x6a: + return 8; + } + case OpenSHC::Map::Units::UT_PRIEST: + switch (_state) { + case 0: + return 1; + case 1: + return 5; + case 2: + case 4: + case 6: + case 7: + case 8: + case 10: + case 0xb: + return 7; + case 3: + return 0x2b; + case 5: + return 0x2a; + case 9: + return this->units[unitIndex].substate + 0x18; + default: + return 0; + case 0x6a: + return 8; + } + case OpenSHC::Map::Units::UT_HEALER: + switch (_state) { + case 0: + return 1; + case 1: + return 5; + default: + return 7; + case 3: + return 0x2d; + case 4: + return 0x2e; + case 5: + return 0x2f; + case 6: + return 0x30; + case 0x6a: + return 8; + } + case OpenSHC::Map::Units::UT_DRUNK: + return DAT_GameState::instance.mapAndTime.drunkenManStatus + 0x75; + case OpenSHC::Map::Units::UT_INNKEEPER: + *pResourceType = OpenSHC::Game::Resources::RT_ALE; + switch (_state) { + case 0: + case 1: + return 1; + case 2: + return 9; + case 3: + return 6; + case 4: + return 5; + case 5: + return 7; + default: + return 0; + case 0x6a: + return 8; + } + case OpenSHC::Map::Units::UT_TRADER: + switch (_state) { + case 0: + return 1; + case 1: + return 0x37; + case 2: + return 7; + case 3: + return 0x38; + default: + return 0; + case 0x6a: + return 8; + } + case OpenSHC::Map::Units::UT_TRADERHORSE: + if (_state == 1) { + return 0x37; + } + if (_state != 3) { + if (_state == 0x6a) { + return 8; + } + return 1; + } + return 0x38; + case OpenSHC::Map::Units::UT_COW: + switch (_state) { + case 0: + if (this->units[unitIndex].substate == 0x66 || this->units[unitIndex].substate == 0x67) { + return 0x3c; + } + default: + return 0x3d; + case 2: + case 4: + case 5: + return 0x3a; + case 3: + return 0x3b; + case 6: + case 0x6e: + return 0xc; + } + case OpenSHC::Map::Units::UT_HUNTERDOG: + switch (_state) { + case 3: + return 0x3f; + case 4: + case 5: + return 0x40; + case 7: + case 8: + return 0x41; + case 9: + return 0x42; + case 0x78: + return 0x43; + } + return 1; + case OpenSHC::Map::Units::UT_FIREFIGHTER: + switch (_state) { + case 0: + case 2: + return 4; + case 1: + return 0x97; + case 3: + return 0x96; + case 4: + return 0x98; + default: + return 0; + case 0x6a: + return 8; + } + case OpenSHC::Map::Units::UT_GHOST: + return (DAT_GameState::instance.mapAndTime.drunkenManStatus & 3U) + 0x99; + case OpenSHC::Map::Units::UT_LADY: + switch (_state) { + case 1: + case 9: + return 0x12; + case 3: + return 0x13; + case 4: + case 8: + return 0x14; + case 5: + return 0x15; + case 6: + return this->units[unitIndex].substate + 0xe; + case 7: + return 0x16; + case ((UnitType)10): + return 0; + case 0x6a: + return 8; + } + return 4; + case OpenSHC::Map::Units::UT_JESTER: + switch (_state) { + case 1: + return 0x45; + default: + return 0x49; + case 3: + case 4: + return 0x46; + case 5: + return 0x47; + case 7: + case 8: + return 0x48; + case 0x6a: + return 8; + } + case OpenSHC::Map::Units::UT_CHICKEN: + if (_state == 2) { + return 0x4c; + } + return 0x4b; + case OpenSHC::Map::Units::UT_MOTHER: + switch (_state) { + case 3: + case 5: + case 6: + case 7: + return 0x4f; + case 4: + return 0x50; + default: + return 0x51; + case 0x65: + if (DAT_BuildingsState::instance.buildings[this->units[unitIndex].targetID_OR_targetBuildingID] + .buildingType + != OpenSHC::Map::Buildings::BT_CHAPEL + && DAT_BuildingsState::instance.buildings[this->units[unitIndex].targetID_OR_targetBuildingID] + .buildingType + != OpenSHC::Map::Buildings::BT_CHURCH + && DAT_BuildingsState::instance.buildings[this->units[unitIndex].targetID_OR_targetBuildingID] + .buildingType + != OpenSHC::Map::Buildings::BT_CATHEDRAL) { + return 0x4f; + } + return 0x4e; + case 0x6a: + return 8; + } + case OpenSHC::Map::Units::UT_CHILD: + switch (_state) { + case 0: + case 1: + return 1; + default: + return 0x57; + case 3: + return 0x53; + case 4: + case 5: + return 0x54; + case 6: + case 9: + return 0x55; + case 10: + case 0xb: + case 0xc: + case 0xd: + return 0x56; + case 0x6a: + return 8; + } + case OpenSHC::Map::Units::UT_JUGGLER: + switch (_state) { + case 0: + return 1; + case 1: + return 0x59; + case 2: + case 3: + case 4: + case 5: + case 6: + return 0x5a; + default: + return 0; + case 0x6a: + return 8; + } + case OpenSHC::Map::Units::UT_FIREEATER: + switch (_state) { + case 0: + return 1; + case 1: + return 0x5c; + case 2: + case 3: + case 4: + return 0x5d; + default: + return 0; + case 0x6a: + return 8; + } + } + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index cd098396a..5ebf67d44 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -51263,7 +51263,7 @@ SHC_3BB0A8C1_0x00537E00 | 35.2% | orig has 2 separate loops SHC_3BB0A8C1_0x00537EE0 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x00537F60 | 0.0% | Pending +SHC_3BB0A8C1_0x00537F60 | 62.5% | jump table order differs SHC_3BB0A8C1_0x005388DC | 0.0% | Pending From 44ed2234b4c4ebf26d39058e7ad40644ccaac975 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 10:32:29 +0200 Subject: [PATCH 191/299] reimplement: SHC_3BB0A8C1_0x00549C70 20.30% orig shares melee tail --- .../UnitsState/processMeleeInitiation.cpp | 604 ++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 605 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/processMeleeInitiation.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/processMeleeInitiation.cpp b/src/OpenSHC/Map/Units/UnitsState/processMeleeInitiation.cpp new file mode 100644 index 000000000..c32e67510 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/processMeleeInitiation.cpp @@ -0,0 +1,604 @@ +#include "OpenSHC/Game/GameStateStructures.func.hpp" +#include "OpenSHC/Map/TileMapState.func.hpp" +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Game/GameMode.hpp" +#include "OpenSHC/Map/Units/States/UnitState.hpp" +#include "OpenSHC/Map/Units/UnitLogicState.hpp" +#include "OpenSHC/Map/Units/UnitType.hpp" + +#include "OpenSHC/Globals/DAT_CurrentUnitSlotID.hpp" +#include "OpenSHC/Globals/DAT_GameState.hpp" +#include "OpenSHC/Globals/DAT_GameSynchronyState.hpp" +#include "OpenSHC/Globals/DAT_MinimapViewState.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_UnitPropertiesDefinedData.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Game::GameMode; + using OpenSHC::Map::Units::UnitLogicState; + using OpenSHC::Map::Units::UnitType; + using OpenSHC::Map::Units::States::UnitState; + + // FUNCTION: STRONGHOLDCRUSADER 0x00549C70 + void UnitsState::processMeleeInitiation(int unitID) + + { + uint _neighbourHeights[8]; + int _totalHeight; + int _playerID; + int _hasEnemyOnOwnTile; + uint _teamBitFlags; + uint* _occupancyRow; + int _adjacentTiles[24]; + int _otherUnitID; + if ((((this->units[unitID].someUnitStat2_meleeDamageUnk != 0) + && (this->units[unitID].unknownTestAgainst0_2 == 0)) + && (this->units[unitID].unknownMovementRelated_0x2d2 == 0)) + && (((this->units[unitID].logicalState == OpenSHC::Map::Units::ULS_NORMAL + && (this->units[unitID].dying == 0)) + && (this->units[unitID].moveRelatedFlag != 1)))) { + int _distanceThreshold; + if (this->units[unitID].stateBasedSpeed < 1) { + /* + 50 or 150 depending on selectable + */ + + if (this->units[unitID].isSelectable_OR_matchTime != 0) { + _distanceThreshold = 150; + } else { + _distanceThreshold = 50; + } + } else { + _distanceThreshold = 270; + } + if (((this->units[unitID].closestEnemyMicroDistance <= _distanceThreshold) + || (this->units[unitID].attackedUnitID != 0)) + || ((this->units[unitID].unitType == OpenSHC::Map::Units::UT_LIONSHWOLF + || ((this->units[unitID].isStalked != 0 + && (((DAT_GameSynchronyState::instance.currentGameMode != OpenSHC::Game::GM_SOLITARY + || (100 < (int)this->unitCount)) + && (((this->units[unitID].fixedRng + ^ DAT_GameState::instance.mapAndTime.totalGameTicksUnk) + & 0xf) + == 0)))))))) { + _totalHeight + = (int)this->units[unitID].buildingHeight + (int)this->units[unitID].terrainOrClimbHeight; + _playerID = (int)this->units[unitID].owner; + DAT_TileMapState::instance.DAT_SomeTile = this->units[unitID].tile; + DAT_TileMapState::instance.DAT_SomeY + = (int)DAT_ViewportRenderState::instance + .tileTranslationMatrix_YComponent[DAT_TileMapState::instance.DAT_SomeTile]; + _hasEnemyOnOwnTile = 0; + _teamBitFlags = MACRO_CALL_MEMBER( + OpenSHC::Game::GameStateStructures_Func::teamToBitFlagsUnk, DAT_GameState::ptr)(unitID); + DAT_TileMapState::instance.field213_0x554a48 = 0; + if ((*(uint*)((uchar*)DAT_TileMapState::instance.ptr_OccupancyLayer + + DAT_TileMapState::instance.DAT_SomeTile + 1) + & _teamBitFlags) + != 0) { + DAT_TileMapState::instance.field213_0x554a48 = 0x20; + } + if ((*(uint*)((uchar*)DAT_TileMapState::instance.ptr_OccupancyLayer + + DAT_TileMapState::instance.DAT_SomeTile + -1) + & _teamBitFlags) + != 0) { + DAT_TileMapState::instance.field213_0x554a48 = DAT_TileMapState::instance.field213_0x554a48 | 2; + } + if ((*(uint*)((uchar*)DAT_TileMapState::instance.ptr_OccupancyLayer + + DAT_TileMapState::instance.DAT_SomeTile + 2) + & _teamBitFlags) + != 0) { + DAT_TileMapState::instance.field213_0x554a48 + = DAT_TileMapState::instance.field213_0x554a48 | 0x80000; + } + if ((*(uint*)((uchar*)DAT_TileMapState::instance.ptr_OccupancyLayer + + DAT_TileMapState::instance.DAT_SomeTile + -2) + & _teamBitFlags) + != 0) { + DAT_TileMapState::instance.field213_0x554a48 + = DAT_TileMapState::instance.field213_0x554a48 | 0x800; + } + _occupancyRow = (uint*)((uchar*)DAT_TileMapState::instance.ptr_OccupancyLayer + + *(int*)((uchar*)DAT_TileMapState::instance.ptr_MovementDirectionTranslationMatrix + + DAT_TileMapState::instance.DAT_SomeY * 0x20) + + DAT_TileMapState::instance.DAT_SomeTile); + if ((*(uint*)((int)_occupancyRow + -1) & _teamBitFlags) != 0) { + DAT_TileMapState::instance.field213_0x554a48 = DAT_TileMapState::instance.field213_0x554a48 | 1; + } + if ((*(uint*)((int)_occupancyRow + 1) & _teamBitFlags) != 0) { + DAT_TileMapState::instance.field213_0x554a48 + = DAT_TileMapState::instance.field213_0x554a48 | 0x40; + } + if ((*_occupancyRow & _teamBitFlags) != 0) { + DAT_TileMapState::instance.field213_0x554a48 + = DAT_TileMapState::instance.field213_0x554a48 | 0x80; + } + if ((*(uint*)((int)_occupancyRow + -2) & _teamBitFlags) != 0) { + DAT_TileMapState::instance.field213_0x554a48 + = DAT_TileMapState::instance.field213_0x554a48 | 0x400; + } + if ((*(uint*)((int)_occupancyRow + 2) & _teamBitFlags) != 0) { + DAT_TileMapState::instance.field213_0x554a48 + = DAT_TileMapState::instance.field213_0x554a48 | 0x100000; + } + _occupancyRow = (uint*)((uchar*)DAT_TileMapState::instance.ptr_OccupancyLayer + + *(int*)((int)((uchar*)DAT_TileMapState::instance.ptr_MovementDirectionTranslationMatrix + + DAT_TileMapState::instance.DAT_SomeY * 0x20) + + 0x10) + + DAT_TileMapState::instance.DAT_SomeTile); + if ((*(uint*)((int)_occupancyRow + -1) & _teamBitFlags) != 0) { + DAT_TileMapState::instance.field213_0x554a48 = DAT_TileMapState::instance.field213_0x554a48 | 4; + } + if ((*(uint*)((int)_occupancyRow + 1) & _teamBitFlags) != 0) { + DAT_TileMapState::instance.field213_0x554a48 + = DAT_TileMapState::instance.field213_0x554a48 | 0x10; + } + if ((*_occupancyRow & _teamBitFlags) != 0) { + DAT_TileMapState::instance.field213_0x554a48 = DAT_TileMapState::instance.field213_0x554a48 | 8; + } + if ((*(uint*)((int)_occupancyRow + -2) & _teamBitFlags) != 0) { + DAT_TileMapState::instance.field213_0x554a48 + = DAT_TileMapState::instance.field213_0x554a48 | 0x1000; + } + if ((*(uint*)((int)_occupancyRow + 2) & _teamBitFlags) != 0) { + DAT_TileMapState::instance.field213_0x554a48 + = DAT_TileMapState::instance.field213_0x554a48 | 0x40000; + } + _occupancyRow = (uint*)((uchar*)DAT_TileMapState::instance.ptr_OccupancyLayer + + *(int*)((uchar*)DAT_TileMapState::instance.ptr_MovementDirectionTranslationMatrix + + DAT_TileMapState::instance.DAT_SomeY * 0x20 + -0x20) + + *(int*)((uchar*)DAT_TileMapState::instance.ptr_MovementDirectionTranslationMatrix + + DAT_TileMapState::instance.DAT_SomeY * 0x20) + + DAT_TileMapState::instance.DAT_SomeTile); + if ((*(uint*)((int)_occupancyRow + -1) & _teamBitFlags) != 0) { + DAT_TileMapState::instance.field213_0x554a48 + = DAT_TileMapState::instance.field213_0x554a48 | 0x100; + } + if ((*(uint*)((int)_occupancyRow + 1) & _teamBitFlags) != 0) { + DAT_TileMapState::instance.field213_0x554a48 + = DAT_TileMapState::instance.field213_0x554a48 | 0x400000; + } + if ((*_occupancyRow & _teamBitFlags) != 0) { + DAT_TileMapState::instance.field213_0x554a48 + = DAT_TileMapState::instance.field213_0x554a48 | 0x800000; + } + if ((*(uint*)((int)_occupancyRow + -2) & _teamBitFlags) != 0) { + DAT_TileMapState::instance.field213_0x554a48 + = DAT_TileMapState::instance.field213_0x554a48 | 0x200; + } + if ((*(uint*)((int)_occupancyRow + 2) & _teamBitFlags) != 0) { + DAT_TileMapState::instance.field213_0x554a48 + = DAT_TileMapState::instance.field213_0x554a48 | 0x200000; + } + _occupancyRow = (uint*)((uchar*)DAT_TileMapState::instance.ptr_OccupancyLayer + + *(int*)((uchar*)DAT_TileMapState::instance.ptr_MovementDirectionTranslationMatrix + + DAT_TileMapState::instance.DAT_SomeY * 0x20 + 0x30) + + *(int*)((uchar*)DAT_TileMapState::instance.ptr_MovementDirectionTranslationMatrix + + DAT_TileMapState::instance.DAT_SomeY * 0x20 + 0x10) + + DAT_TileMapState::instance.DAT_SomeTile); + if ((*(uint*)((int)_occupancyRow + -1) & _teamBitFlags) != 0) { + DAT_TileMapState::instance.field213_0x554a48 + = DAT_TileMapState::instance.field213_0x554a48 | 0x4000; + } + if ((*(uint*)((int)_occupancyRow + 1) & _teamBitFlags) != 0) { + DAT_TileMapState::instance.field213_0x554a48 + = DAT_TileMapState::instance.field213_0x554a48 | 0x10000; + } + if ((*_occupancyRow & _teamBitFlags) != 0) { + DAT_TileMapState::instance.field213_0x554a48 + = DAT_TileMapState::instance.field213_0x554a48 | 0x8000; + } + if ((*(uint*)((int)_occupancyRow + -2) & _teamBitFlags) != 0) { + DAT_TileMapState::instance.field213_0x554a48 + = DAT_TileMapState::instance.field213_0x554a48 | 0x2000; + } + if ((*(uint*)((int)_occupancyRow + 2) & _teamBitFlags) != 0) { + DAT_TileMapState::instance.field213_0x554a48 + = DAT_TileMapState::instance.field213_0x554a48 | 0x20000; + } + for (_otherUnitID + = (short)DAT_TileMapState::instance.UnitLayer[DAT_TileMapState::instance.DAT_SomeTile]; + _otherUnitID > 0; _otherUnitID = (short)this->units[_otherUnitID].nextUnitOnTheSameTile) { + if (_otherUnitID != unitID) { + bool _isFriendly; + if (this->units[unitID].owner == 0) { + _isFriendly = this->units[unitID].unitType == this->units[_otherUnitID].unitType; + } else { + _isFriendly = DAT_GameState::instance.mapAndTime.playerTeams[_playerID] + == DAT_GameState::instance.mapAndTime.playerTeams[this->units[_otherUnitID].owner]; + } + if (!_isFriendly) { + _hasEnemyOnOwnTile = 1; + break; + } + } + } + if ((DAT_TileMapState::instance.field213_0x554a48 != 0) || (_hasEnemyOnOwnTile != 0)) { + for (int i = 0; i < 24; ++i) { + _adjacentTiles[i] = 0; + } + if ((DAT_TileMapState::instance.field213_0x554a48 & 1) != 0) { + _adjacentTiles[0] = DAT_TileMapState::instance + .directionTranslationMatrix[DAT_TileMapState::instance.DAT_SomeY][7] + + this->units[unitID].tile; + } + if ((DAT_TileMapState::instance.field213_0x554a48 & 2) != 0) { + _adjacentTiles[1] = DAT_TileMapState::instance + .directionTranslationMatrix[DAT_TileMapState::instance.DAT_SomeY][6] + + this->units[unitID].tile; + } + if ((DAT_TileMapState::instance.field213_0x554a48 & 4) != 0) { + _adjacentTiles[2] = DAT_TileMapState::instance + .directionTranslationMatrix[DAT_TileMapState::instance.DAT_SomeY][5] + + this->units[unitID].tile; + } + if ((DAT_TileMapState::instance.field213_0x554a48 & 8) != 0) { + _adjacentTiles[3] = DAT_TileMapState::instance + .directionTranslationMatrix[DAT_TileMapState::instance.DAT_SomeY][4] + + this->units[unitID].tile; + } + if ((DAT_TileMapState::instance.field213_0x554a48 & 0x10) != 0) { + _adjacentTiles[4] = DAT_TileMapState::instance + .directionTranslationMatrix[DAT_TileMapState::instance.DAT_SomeY][3] + + this->units[unitID].tile; + } + if ((DAT_TileMapState::instance.field213_0x554a48 & 0x20) != 0) { + _adjacentTiles[5] = DAT_TileMapState::instance + .directionTranslationMatrix[DAT_TileMapState::instance.DAT_SomeY][2] + + this->units[unitID].tile; + } + if ((DAT_TileMapState::instance.field213_0x554a48 & 0x40) != 0) { + _adjacentTiles[6] = DAT_TileMapState::instance + .directionTranslationMatrix[DAT_TileMapState::instance.DAT_SomeY][1] + + this->units[unitID].tile; + } + if ((char)DAT_TileMapState::instance.field213_0x554a48 < '\0') { + _adjacentTiles[7] = DAT_TileMapState::instance + .directionTranslationMatrix[DAT_TileMapState::instance.DAT_SomeY][0] + + this->units[unitID].tile; + } + _neighbourHeights[0] = MACRO_CALL_MEMBER( + OpenSHC::Map::TileMapState_Func::getTotalHeightAtTile, DAT_TileMapState::ptr)( + DAT_TileMapState::instance + .directionTranslationMatrix[DAT_TileMapState::instance.DAT_SomeY][7] + + this->units[unitID].tile); + _neighbourHeights[1] = MACRO_CALL_MEMBER( + OpenSHC::Map::TileMapState_Func::getTotalHeightAtTile, DAT_TileMapState::ptr)( + DAT_TileMapState::instance + .directionTranslationMatrix[DAT_TileMapState::instance.DAT_SomeY][6] + + this->units[unitID].tile); + _neighbourHeights[2] = MACRO_CALL_MEMBER( + OpenSHC::Map::TileMapState_Func::getTotalHeightAtTile, DAT_TileMapState::ptr)( + DAT_TileMapState::instance + .directionTranslationMatrix[DAT_TileMapState::instance.DAT_SomeY][5] + + this->units[unitID].tile); + _neighbourHeights[3] = MACRO_CALL_MEMBER( + OpenSHC::Map::TileMapState_Func::getTotalHeightAtTile, DAT_TileMapState::ptr)( + DAT_TileMapState::instance + .directionTranslationMatrix[DAT_TileMapState::instance.DAT_SomeY][4] + + this->units[unitID].tile); + _neighbourHeights[4] = MACRO_CALL_MEMBER( + OpenSHC::Map::TileMapState_Func::getTotalHeightAtTile, DAT_TileMapState::ptr)( + DAT_TileMapState::instance + .directionTranslationMatrix[DAT_TileMapState::instance.DAT_SomeY][3] + + this->units[unitID].tile); + _neighbourHeights[5] = MACRO_CALL_MEMBER( + OpenSHC::Map::TileMapState_Func::getTotalHeightAtTile, DAT_TileMapState::ptr)( + DAT_TileMapState::instance + .directionTranslationMatrix[DAT_TileMapState::instance.DAT_SomeY][2] + + this->units[unitID].tile); + _neighbourHeights[6] = MACRO_CALL_MEMBER( + OpenSHC::Map::TileMapState_Func::getTotalHeightAtTile, DAT_TileMapState::ptr)( + DAT_TileMapState::instance + .directionTranslationMatrix[DAT_TileMapState::instance.DAT_SomeY][1] + + this->units[unitID].tile); + _neighbourHeights[7] = MACRO_CALL_MEMBER( + OpenSHC::Map::TileMapState_Func::getTotalHeightAtTile, DAT_TileMapState::ptr)( + DAT_TileMapState::instance + .directionTranslationMatrix[DAT_TileMapState::instance.DAT_SomeY][0] + + this->units[unitID].tile); + if ((DAT_TileMapState::instance.field213_0x554a48 & 0x100) != 0) { + _adjacentTiles[8] = DAT_MinimapViewState::instance + .spawnMoment[DAT_TileMapState::instance.DAT_SomeY * 8 + 0x14] + + this->units[unitID].tile + + DAT_TileMapState::instance + .directionTranslationMatrix[DAT_TileMapState::instance.DAT_SomeY][0]; + } + if ((DAT_TileMapState::instance.field213_0x554a48 & 0x200) != 0) { + _adjacentTiles[9] = DAT_MinimapViewState::instance + .spawnMoment[DAT_TileMapState::instance.DAT_SomeY * 8 + 0x13] + + DAT_MinimapViewState::instance + .spawnMoment[DAT_TileMapState::instance.DAT_SomeY * 8 + 0x14] + + this->units[unitID].tile + + DAT_TileMapState::instance + .directionTranslationMatrix[DAT_TileMapState::instance.DAT_SomeY][0]; + } + if ((DAT_TileMapState::instance.field213_0x554a48 & 0x400) != 0) { + _adjacentTiles[10] + = DAT_TileMapState::instance + .directionTranslationMatrix[DAT_TileMapState::instance.DAT_SomeY][6] + + DAT_TileMapState::instance + .directionTranslationMatrix[DAT_TileMapState::instance.DAT_SomeY][7] + + this->units[unitID].tile; + } + if ((DAT_TileMapState::instance.field213_0x554a48 & 0x800) != 0) { + _adjacentTiles[0xb] = this->units[unitID].tile + + DAT_TileMapState::instance + .directionTranslationMatrix[DAT_TileMapState::instance.DAT_SomeY][6] + * 2; + } + if ((DAT_TileMapState::instance.field213_0x554a48 & 0x1000) != 0) { + _adjacentTiles[0xc] + = DAT_TileMapState::instance + .directionTranslationMatrix[DAT_TileMapState::instance.DAT_SomeY][5] + + DAT_TileMapState::instance + .directionTranslationMatrix[DAT_TileMapState::instance.DAT_SomeY][6] + + this->units[unitID].tile; + } + if ((DAT_TileMapState::instance.field213_0x554a48 & 0x2000) != 0) { + _adjacentTiles[0xd] + = DAT_TileMapState::instance + .directionTranslationMatrix[DAT_TileMapState::instance.DAT_SomeY + 1][6] + + DAT_TileMapState::instance + .directionTranslationMatrix[DAT_TileMapState::instance.DAT_SomeY + 1][5] + + DAT_TileMapState::instance + .directionTranslationMatrix[DAT_TileMapState::instance.DAT_SomeY][4] + + this->units[unitID].tile; + } + if ((DAT_TileMapState::instance.field213_0x554a48 & 0x4000) != 0) { + _adjacentTiles[0xe] + = DAT_TileMapState::instance + .directionTranslationMatrix[DAT_TileMapState::instance.DAT_SomeY + 1][5] + + DAT_TileMapState::instance + .directionTranslationMatrix[DAT_TileMapState::instance.DAT_SomeY][4] + + this->units[unitID].tile; + } + if ((DAT_TileMapState::instance.field213_0x554a48 & 0x8000) != 0) { + _adjacentTiles[0xf] + = DAT_TileMapState::instance + .directionTranslationMatrix[DAT_TileMapState::instance.DAT_SomeY + 1][4] + + DAT_TileMapState::instance + .directionTranslationMatrix[DAT_TileMapState::instance.DAT_SomeY][4] + + this->units[unitID].tile; + } + if ((DAT_TileMapState::instance.field213_0x554a48 & 0x10000) != 0) { + _adjacentTiles[0x10] + = DAT_TileMapState::instance + .directionTranslationMatrix[DAT_TileMapState::instance.DAT_SomeY + 1][3] + + DAT_TileMapState::instance + .directionTranslationMatrix[DAT_TileMapState::instance.DAT_SomeY][4] + + this->units[unitID].tile; + } + if ((DAT_TileMapState::instance.field213_0x554a48 & 0x20000) != 0) { + _adjacentTiles[0x11] + = DAT_TileMapState::instance + .directionTranslationMatrix[DAT_TileMapState::instance.DAT_SomeY + 1][2] + + DAT_TileMapState::instance + .directionTranslationMatrix[DAT_TileMapState::instance.DAT_SomeY + 1][3] + + DAT_TileMapState::instance + .directionTranslationMatrix[DAT_TileMapState::instance.DAT_SomeY][4] + + this->units[unitID].tile; + } + if ((DAT_TileMapState::instance.field213_0x554a48 & 0x40000) != 0) { + _adjacentTiles[0x12] + = DAT_TileMapState::instance + .directionTranslationMatrix[DAT_TileMapState::instance.DAT_SomeY][2] + + DAT_TileMapState::instance + .directionTranslationMatrix[DAT_TileMapState::instance.DAT_SomeY][3] + + this->units[unitID].tile; + } + if ((DAT_TileMapState::instance.field213_0x554a48 & 0x80000) != 0) { + _adjacentTiles[0x13] = this->units[unitID].tile + + DAT_TileMapState::instance + .directionTranslationMatrix[DAT_TileMapState::instance.DAT_SomeY][2] + * 2; + } + if ((DAT_TileMapState::instance.field213_0x554a48 & 0x100000) != 0) { + _adjacentTiles[0x14] + = DAT_TileMapState::instance + .directionTranslationMatrix[DAT_TileMapState::instance.DAT_SomeY][1] + + DAT_TileMapState::instance + .directionTranslationMatrix[DAT_TileMapState::instance.DAT_SomeY][2] + + this->units[unitID].tile; + } + if ((DAT_TileMapState::instance.field213_0x554a48 & 0x200000) != 0) { + _adjacentTiles[0x15] = DAT_MinimapViewState::instance + .spawnMoment[DAT_TileMapState::instance.DAT_SomeY * 8 + 0xe] + + DAT_MinimapViewState::instance + .spawnMoment[DAT_TileMapState::instance.DAT_SomeY * 8 + 0xf] + + this->units[unitID].tile + + DAT_TileMapState::instance + .directionTranslationMatrix[DAT_TileMapState::instance.DAT_SomeY][0]; + } + if ((DAT_TileMapState::instance.field213_0x554a48 & 0x400000) != 0) { + _adjacentTiles[0x16] = DAT_MinimapViewState::instance + .spawnMoment[DAT_TileMapState::instance.DAT_SomeY * 8 + 0xe] + + this->units[unitID].tile + + DAT_TileMapState::instance + .directionTranslationMatrix[DAT_TileMapState::instance.DAT_SomeY][0]; + } + if ((DAT_TileMapState::instance.field213_0x554a48 & 0x800000) != 0) { + _adjacentTiles[0x17] = DAT_MinimapViewState::instance + .spawnMoment[DAT_TileMapState::instance.DAT_SomeY * 8 + 0xd] + + this->units[unitID].tile + + DAT_TileMapState::instance + .directionTranslationMatrix[DAT_TileMapState::instance.DAT_SomeY][0]; + } + if (this->units[unitID].attackedUnitID != 0) { + _otherUnitID = this->units[unitID].attackedUnitID; + if (this->units[_otherUnitID].uid == this->units[unitID].field191_0x340 + && this->units[_otherUnitID].logicalState == OpenSHC::Map::Units::ULS_NORMAL + && this->units[_otherUnitID].dying == 0) { + /* -- CHECK 24 TILES AROUND UNIT -- is the unit we already fight still in reach? */ + for (int _slot = -1; _slot < 24; ++_slot) { + int _candidateTile; + if (_slot == -1) { + if (_hasEnemyOnOwnTile == 0) { + continue; + } + _candidateTile = this->units[unitID].tile; + } else { + _candidateTile = _adjacentTiles[DAT_UnitPropertiesDefinedData::instance + .field117_0x11cf4[this->units[unitID].facingDirection][_slot]]; + } + if (_candidateTile == 0) { + continue; + } + int _heightDelta = _totalHeight + - MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getTotalHeightAtTile, + DAT_TileMapState::ptr)(_candidateTile); + if (_heightDelta < 0) { + _heightDelta = -_heightDelta; + } + if (_heightDelta >= 0x20) { + continue; + } + if (_otherUnitID + == MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::getEnemyUnitIDNearby, + this)(unitID, _candidateTile, _totalHeight)) { + MACRO_CALL_MEMBER( + OpenSHC::Map::Units::UnitsState_Func::setFacingDirectionTowardUnitMicro, + this)(unitID, _otherUnitID); + if (this->units[unitID].state.generic + != OpenSHC::Map::Units::States::US_MELEE_ATTACK) { + if (this->units[unitID].movementRelated == 8) { + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func:: + saveUnitStateBeforeInterruption, + this)(unitID); + this->units[unitID].movementRelated = 8; + this->units[unitID].state.generic + = OpenSHC::Map::Units::States::US_MELEE_ATTACK; + this->units[unitID].SA = 0; + this->units[unitID].animationCycleNumber = 0; + this->units[DAT_CurrentUnitSlotID::instance].substate = 0; + } else { + this->units[unitID].field259_0x3d2 = 1; + } + } + MACRO_CALL_MEMBER( + OpenSHC::Map::Units::UnitsState_Func::processUnitAttackOtherUnit, this)( + DAT_CurrentUnitSlotID::instance, this->units[unitID].attackedUnitID); + return; + } + } + } + this->units[unitID].attackedUnitID = 0; + this->units[unitID].field191_0x340 = 0; + this->units[unitID].field259_0x3d2 = 0; + } + /* -- CHECK 24 TILES AROUND UNIT -- look for someone new to fight */ + for (int _slot = -1; _slot < 24; ++_slot) { + int _candidateTile; + int _tileSlot; + if (_slot == -1) { + if (_hasEnemyOnOwnTile == 0) { + continue; + } + _tileSlot = this->units[unitID].facingDirection; + _candidateTile = this->units[unitID].tile; + } else { + _tileSlot = DAT_UnitPropertiesDefinedData::instance + .field117_0x11cf4[this->units[unitID].facingDirection][_slot]; + _candidateTile = _adjacentTiles[_tileSlot]; + } + if (_candidateTile == 0) { + continue; + } + if (_tileSlot >= 8) { + int _firstHeightDelta = _totalHeight + - _neighbourHeights + [DAT_UnitPropertiesDefinedData::instance.field118_0x12054[_tileSlot].x]; + if (_firstHeightDelta < 0) { + _firstHeightDelta = -_firstHeightDelta; + } + if (_firstHeightDelta >= 0x21) { + continue; + } + int _secondHeightIndex + = DAT_UnitPropertiesDefinedData::instance.field118_0x12054[_tileSlot].y; + if (_secondHeightIndex != -1) { + int _secondHeightDelta = _totalHeight - _neighbourHeights[_secondHeightIndex]; + if (_secondHeightDelta < 0) { + _secondHeightDelta = -_secondHeightDelta; + } + if (_secondHeightDelta >= 0x21) { + continue; + } + } + } + _otherUnitID = MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::getEnemyUnitIDNearby, + this)(unitID, _candidateTile, _totalHeight); + if (_otherUnitID < 1) { + continue; + } + if (this->units[_otherUnitID].logicalState != OpenSHC::Map::Units::ULS_NORMAL) { + continue; + } + if (this->units[_otherUnitID].dying != 0) { + continue; + } + int _targetHeightDelta = (_totalHeight - this->units[_otherUnitID].buildingHeight) + - this->units[_otherUnitID].terrainOrClimbHeight; + if (_targetHeightDelta < 0) { + _targetHeightDelta = -_targetHeightDelta; + } + if (_targetHeightDelta >= 0x21) { + continue; + } + if ((this->units[unitID].unitType == OpenSHC::Map::Units::UT_LIONSHWOLF + || this->units[unitID].unitType == OpenSHC::Map::Units::UT_CAGEDOG) + && this->units[_otherUnitID].isStalked != 0 && _slot >= 8) { + continue; + } + this->units[unitID].attackedUnitID = (short)_otherUnitID; + this->units[unitID].field191_0x340 = this->units[_otherUnitID].uid; + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::setFacingDirectionTowardUnitMicro, + this)(unitID, _otherUnitID); + break; + } + if (this->units[unitID].attackedUnitID != 0) { + if (this->units[_otherUnitID].someUnitStat2_meleeDamageUnk != 0 + && this->units[_otherUnitID].attackedUnitID == 0 + && this->units[_otherUnitID].unknownMovementRelated_0x2d2 == 0) { + this->units[_otherUnitID].attackedUnitID = (short)unitID; + this->units[_otherUnitID].field191_0x340 = this->units[unitID].uid; + MACRO_CALL_MEMBER( + OpenSHC::Map::Units::UnitsState_Func::setFacingDirectionTowardUnitMicro, this)( + _otherUnitID, unitID); + } + if (this->units[unitID].state.generic != OpenSHC::Map::Units::States::US_MELEE_ATTACK) { + if (this->units[unitID].movementRelated == 8) { + MACRO_CALL_MEMBER( + OpenSHC::Map::Units::UnitsState_Func::saveUnitStateBeforeInterruption, this)( + unitID); + this->units[unitID].movementRelated = 8; + this->units[unitID].state.generic = OpenSHC::Map::Units::States::US_MELEE_ATTACK; + this->units[unitID].SA = 0; + this->units[unitID].animationCycleNumber = 0; + this->units[DAT_CurrentUnitSlotID::instance].substate = 0; + } else { + this->units[unitID].field259_0x3d2 = 1; + } + } + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::processUnitAttackOtherUnit, this)( + DAT_CurrentUnitSlotID::instance, this->units[unitID].attackedUnitID); + return; + } + this->units[unitID].field259_0x3d2 = 0; + this->units[unitID].attackedUnitID = 0; + this->units[unitID].field191_0x340 = 0; + return; + } + } + this->units[unitID].field191_0x340 = 0; + this->units[unitID].attackedUnitID = 0; + this->units[unitID].field259_0x3d2 = 0; + } + } + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 5ebf67d44..984ae3bb8 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -61405,7 +61405,7 @@ SHC_3BB0A8C1_0x00549B24 | 0.0% | Pending SHC_3BB0A8C1_0x00549B30 | 0.0% | Pending -SHC_3BB0A8C1_0x00549C70 | 0.0% | Pending +SHC_3BB0A8C1_0x00549C70 | 20.3% | orig shares melee tail SHC_3BB0A8C1_0x0054A770 | 100.0% | Reimplemented From 274e52a600052c5e851b1da30d9dfb0b0a85b294 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 10:37:54 +0200 Subject: [PATCH 192/299] reimplement: SHC_3BB0A8C1_0x00531920 17.98% orig merges pos blocks --- .../UnitsState/processEntityDamageToUnit.cpp | 522 ++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 523 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/processEntityDamageToUnit.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/processEntityDamageToUnit.cpp b/src/OpenSHC/Map/Units/UnitsState/processEntityDamageToUnit.cpp new file mode 100644 index 000000000..5bbe4cf1b --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/processEntityDamageToUnit.cpp @@ -0,0 +1,522 @@ +#include "OpenSHC/Audio/SFX/SFXState.func.hpp" +#include "OpenSHC/Map/Navigation/DirectionAlgorithmState.func.hpp" +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/DE/SHCDE/eSFX.hpp" +#include "OpenSHC/Game/GameMode.hpp" +#include "OpenSHC/Map/Entities/EntityType.hpp" +#include "OpenSHC/Map/Entities/EntityTypeShort.hpp" +#include "OpenSHC/Map/Units/States/UnitState.hpp" +#include "OpenSHC/Map/Units/UnitType.hpp" +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_DirectionAlgorithmState.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_SFXState.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_TribesState.hpp" +#include "OpenSHC/Globals/DAT_UnitPropertiesDefinedData.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::DE::SHCDE::eSFX; + using OpenSHC::Game::GameMode; + using OpenSHC::Map::Entities::EntityType; + using OpenSHC::Map::Entities::EntityTypeShort; + using OpenSHC::Map::Units::UnitType; + using OpenSHC::Map::Units::States::UnitState; + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x00531920 + BOOLEnum UnitsState::processEntityDamageToUnit(int unitID, int entityID, int tileDistance) + + { + short sVar3; + bool bVar4; + int _cowDiseaseDamage; + int _healthPercentage; + int _unitAltitude; + int _healthPercentage_2; + uint uVar5; + int _entityShootingUnitID_2; + int _unitHeight; + int _damage; + eSFX sfxOffsetInArray; + bool _siegeProjectile; + short _entityShootingUnitID; + EntityTypeShort _entityType; + UnitTypeShort _entityType_2; + int* _unitHealth_ptr; + bool _unitIsSiegeEngine; + + /* + unclear what it does, but this function removes health from a unit, ranged + and melee + */ + + int _unknown = (int)this->units[unitID].tribeID; + _unitIsSiegeEngine = false; + _siegeProjectile = false; + bVar4 = false; + UnitTypeShort _unitType = this->units[unitID].unitType; + _entityShootingUnitID = DAT_EntityState::instance.entityArray[entityID].unitID_OR_seaGullID; + _entityShootingUnitID_2 = (int)_entityShootingUnitID; + if (unitID < 1) { + return FALSE; + } + if (_entityShootingUnitID_2 == unitID) { + return FALSE; + } + _entityType = DAT_EntityState::instance.entityArray[entityID].entityType; + if (_entityType == OpenSHC::Map::Entities::ET_FIRE) { + return FALSE; + } + if (_entityType == OpenSHC::Map::Entities::ET_FIRETHROWER) { + return FALSE; + } + if (_entityType == OpenSHC::Map::Entities::ET_COW_POISON_CLOUD) { + /* + if the unit is dead, don't bother + */ + + if (this->units[unitID].dying != 0) { + return FALSE; + } + _entityShootingUnitID_2 = this->units[unitID].tile; + /* + if the tile that the unit is on has some properties, don't bother either. + */ + + if ((DAT_TileMapState::instance.LogicLayer[_entityShootingUnitID_2] & 0x10000100U) != 0) { + return FALSE; + } + /* + if the unit is standing on a building, and that building is a defensive + building, return 0 + */ + + if (DAT_TileMapState::instance.BuildingLayer[_entityShootingUnitID_2] != 0) { + switch (DAT_BuildingsState::instance + .buildings[DAT_TileMapState::instance.BuildingLayer[_entityShootingUnitID_2]] + .buildingType) { + 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_WOODGATE1: + 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: + return FALSE; + } + } + /* + if the unit is of a type that is invulnerable to disease clouds, return 0 + */ + + if (DAT_UnitPropertiesDefinedData::instance.UnitClimbStateFlags[0][(short)this->units[unitID].unitType] + == 0) { + return FALSE; + } + if (tileDistance == 0) { + _cowDiseaseDamage = 400; + } else { + _cowDiseaseDamage = (-(uint)(tileDistance != 1) & 0xffffffce) + 200; + } + int _healerCount = DAT_GameState::instance.playerDataArray[this->units[unitID].owner].healerCount; + if (_healerCount >= 3) { + /* * 40 */ + _cowDiseaseDamage = (_cowDiseaseDamage * 0x28) / 100; + } else if (_healerCount == 2) { + /* * 60 */ + _cowDiseaseDamage = (_cowDiseaseDamage * 0x3c) / 100; + } else if (_healerCount == 1) { + /* * 80 */ + _cowDiseaseDamage = (_cowDiseaseDamage * 0x50) / 100; + } + _unitHealth_ptr = &this->units[unitID].health; + *_unitHealth_ptr = *_unitHealth_ptr - _cowDiseaseDamage; + if (this->units[unitID].health < 1) { + this->units[unitID].health = 0; + this->units[unitID].dying = 1; + this->units[unitID].animationCycleNumber = 0; + this->units[unitID].state.generic = OpenSHC::Map::Units::States::US_STONE_DEATH_02; + this->units[unitID].tunnelerFinishedDigging = 1; + } + _healthPercentage + = MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::DirectionAlgorithmState_Func::computeHealthPercentage, + DAT_DirectionAlgorithmState::ptr)(this->units[unitID].health, this->units[unitID].maxHealth); + this->units[unitID].healthPercentage = (short)_healthPercentage; + this->units[unitID].healthbar = (short)_healthPercentage / 10; + return FALSE; + } + if (_unitType == OpenSHC::Map::Units::UT_S_TREBUCHET) { + _unitHeight = (-(uint)(tileDistance != 0) & 0xffffffd8) + 0x50; + _unitIsSiegeEngine = true; + } else if (_unitType == OpenSHC::Map::Units::UT_S_TOWER) { + _unitHeight = 0x50; + _unitIsSiegeEngine = true; + } else if (_unitType == OpenSHC::Map::Units::UT_S_CATAPULT) { + _unitHeight = 0x32; + _unitIsSiegeEngine = true; + } else if (_unitType == OpenSHC::Map::Units::UT_S_SHIELD) { + _unitHeight = 0x5a; + _unitIsSiegeEngine = true; + } else if (_unitType == OpenSHC::Map::Units::UT_S_BATTERINGRAM) { + _unitHeight = 0x28; + _unitIsSiegeEngine = true; + } else if (_unitType == OpenSHC::Map::Units::UT_S_MANGONEL) { + _unitHeight = 0x46; + _unitIsSiegeEngine = true; + } else { + if ((_unitType == OpenSHC::Map::Units::UT_S_BALLISTA) + || (_unitType == OpenSHC::Map::Units::UT_S_FBALLISTA)) { + _unitIsSiegeEngine = true; + } + _unitHeight = 42; + } + if ((((_entityType == OpenSHC::Map::Entities::ET_TREBUCHET) + || (_entityType == OpenSHC::Map::Entities::ET_CATAPULT)) + || (_entityType == OpenSHC::Map::Entities::ET_MANGONEL)) + || ((_entityType == OpenSHC::Map::Entities::ET_BALLISTA + || (_entityType == OpenSHC::Map::Entities::ET_FIREBALLISTA)))) { + _siegeProjectile = true; + } + short _unitPlayerID = this->units[unitID].owner; + short _entityPlayerID = DAT_EntityState::instance.entityArray[entityID].owner; + if (((DAT_GameState::instance.mapAndTime.playerTeams[_entityPlayerID] + == DAT_GameState::instance.mapAndTime.playerTeams[_unitPlayerID]) + && (( + ((!_siegeProjectile + || (_entityType = DAT_EntityState::instance.entityArray[entityID].entityType, + _entityType == OpenSHC::Map::Entities::ET_BALLISTA)) + || ((_entityType == OpenSHC::Map::Entities::ET_MANGONEL + && (DAT_GameSynchronyState::instance.currentPlayerFullIDArray[_entityPlayerID] == -1)))) + || ((((_entityType == OpenSHC::Map::Entities::ET_FIREBALLISTA + || (_unitType == OpenSHC::Map::Units::UT_S_SHIELD)) + || (_unitType == OpenSHC::Map::Units::UT_S_TOWER)) + || (_unitType == OpenSHC::Map::Units::UT_S_BATTERINGRAM)))))) + || (this->units[unitID].dying != 0)) { + return FALSE; + } + _unitAltitude = (int)this->units[unitID].terrainOrClimbHeight + (int)this->units[unitID].buildingHeight; + _damage = (int)DAT_EntityState::instance.entityArray[entityID].height; + if (_damage < _unitAltitude) { + return FALSE; + } + if (_unitAltitude + _unitHeight < _damage) { + return FALSE; + } + if ((_entityPlayerID != 0) && (_entityPlayerID != this->units[unitID].owner)) { + this->units[unitID].lastEncounteredEnemyPlayerID = _entityPlayerID; + this->units[unitID].lastEncounteredEnemyUnitIDUnk + = DAT_EntityState::instance.entityArray[entityID].unitID_OR_seaGullID; + } + if ((DAT_GameSynchronyState::instance.currentGameMode != OpenSHC::Game::GM_SOLITARY) + && (_unitPlayerID == DAT_GameSynchronyState::instance.currentPlayerSlotID)) { + MACRO_CALL_MEMBER(OpenSHC::Audio::SFX::SFXState_Func::playSFXWeAreUnderAttack, DAT_SFXState::ptr)(); + } + int _unitYPosition_2 = this->units[unitID].y; + int _unitXPosition_2 = this->units[unitID].x; + _entityType = DAT_EntityState::instance.entityArray[entityID].entityType; + if (_siegeProjectile) { + if (_entityType == OpenSHC::Map::Entities::ET_COW_FLYING) { + _entityType_2 = this->units[unitID].unitType; + if (_entityType_2 == OpenSHC::Map::Units::UT_LORD) { + _damage = 0x32; + } else { + uVar5 = -(uint)(_entityType_2 != OpenSHC::Map::Units::UT_S_SHIELD) & 0x1c2; + } + } else if (_entityType == OpenSHC::Map::Entities::ET_MANGONEL) { + /* + mangonel damage + */ + + _entityType_2 = this->units[unitID].unitType; + if (_entityType_2 == OpenSHC::Map::Units::UT_LORD) { + _damage = 0x32; + } else if (_entityType_2 == OpenSHC::Map::Units::UT_S_SHIELD) { + _damage = 1500; + } else if (_entityType_2 == OpenSHC::Map::Units::UT_S_BALLISTA) { + _damage = 1000; + } else if (_entityType_2 == OpenSHC::Map::Units::UT_S_FBALLISTA) { + _damage = 1000; + } else if (_entityType_2 == OpenSHC::Map::Units::UT_S_MANGONEL) { + _damage = 500; + } else if (_entityType_2 == OpenSHC::Map::Units::UT_S_CATAPULT) { + _damage = 5000; + } else if (_entityType_2 == OpenSHC::Map::Units::UT_S_TREBUCHET) { + _damage = 5000; + } else if (_entityType_2 == OpenSHC::Map::Units::UT_S_BATTERINGRAM) { + _damage = 10000; + } else { + _damage = (-(uint)(_entityType_2 != OpenSHC::Map::Units::UT_S_TOWER) & 20000) + 10000; + } + } else { + if (_entityType != OpenSHC::Map::Entities::ET_BALLISTA) { + uVar5 = -(uint)(this->units[unitID].unitType != OpenSHC::Map::Units::UT_LORD) & 0x74fe; + _damage = uVar5 + 0x32; + } + /* + tower ballista and fire ballista damage + */ + + UnitTypeShort _targetUnitType = this->units[unitID].unitType; + if (_targetUnitType == OpenSHC::Map::Units::UT_LORD) { + _damage = 0x32; + } else if (_targetUnitType == OpenSHC::Map::Units::UT_S_SHIELD) { + _damage = 500; + } else if (_targetUnitType == OpenSHC::Map::Units::UT_S_BALLISTA) { + _damage = 2000; + } else if (_targetUnitType == OpenSHC::Map::Units::UT_S_MANGONEL) { + _damage = 2000; + } else if (_targetUnitType == OpenSHC::Map::Units::UT_S_FBALLISTA) { + _damage = 2000; + } else if (_targetUnitType == OpenSHC::Map::Units::UT_S_CATAPULT) { + _damage = 0x9c4; + } else if (_targetUnitType == OpenSHC::Map::Units::UT_S_TREBUCHET) { + _damage = 4000; + } else if (_targetUnitType == OpenSHC::Map::Units::UT_S_BATTERINGRAM) { + _damage = 20000; + } else { + /* + 10000 if not siege tower else 20000 + */ + + _damage = (-(uint)(_targetUnitType != OpenSHC::Map::Units::UT_S_TOWER) & 0xffffd8f0) + 20000; + } + if (DAT_EntityState::instance.entityArray[entityID].field90_0xd0 != 0) { + /* + if is fire ballista + */ + + _damage = (_damage * 2) / 3; + } + } + DAT_GameCore::instance.cowPoisonTrackerUnk = DAT_GameCore::instance.cowPoisonTrackerUnk + 0x32; + if (20000 < _damage) { + this->units[unitID].dying = 1; + if (0 < _unknown) { + DAT_TribesState::instance.tribes[_unknown].field133_0x278 = 1; + } + short _unitYPosition = this->units[unitID].y; + short _unitXPosition = this->units[unitID].x; + this->units[unitID].animationCycleNumber = 0; + this->units[unitID].state.generic = OpenSHC::Map::Units::States::US_STONE_DEATH_01; + this->units[unitID].tunnelerFinishedDigging = 1; + MACRO_CALL_MEMBER(OpenSHC::Audio::SFX::SFXState_Func::playSFXAtLocation, DAT_SFXState::ptr)( + (int)_unitXPosition, (int)((int)(_unitYPosition)), OpenSHC::DE::SHCDE::FX_SPLAT); + this->units[unitID].health = 0; + return TRUE; + } + } else { + if (_entityType == OpenSHC::Map::Entities::ET_ARROW_AND_DEFAULT) { + _entityType_2 = this->units[unitID].unitType; + _damage = DAT_UnitPropertiesDefinedData::instance.ARROW_DAMAGE[(short)_entityType_2]; + if ((_entityType_2 == OpenSHC::Map::Units::UT_E_LADDER) + && (this->units[unitID].state.generic == ((UnitState)3))) { + _damage = (int)(_damage + (_damage >> 0x1f & 3U)) >> 2; + } + } else if (_entityType == OpenSHC::Map::Entities::ET_SLINGER) { + _damage = DAT_UnitPropertiesDefinedData::instance.STONE_DAMAGE[(short)this->units[unitID].unitType]; + } else { + _damage = DAT_UnitPropertiesDefinedData::instance.BOLT_DAMAGE[(short)this->units[unitID].unitType]; + } + _damage = MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::computeDamageFearFactorBonus, this)( + _damage, (int)((int)(DAT_EntityState::instance.entityArray[entityID].owner))); + if (_unitIsSiegeEngine) { + _damage = _damage / 2; + } + if (this->units[unitID].isStalked == 0) { + DAT_GameCore::instance.cowPoisonTrackerUnk = DAT_GameCore::instance.cowPoisonTrackerUnk + 0x32; + } + } + if ((int)DAT_EntityState::instance.entityArray[entityID].startingHeight + < DAT_EntityState::instance.entityArray[entityID].targetZ + -0x1e) { + if ((this->units[unitID].unitType == OpenSHC::Map::Units::UT_E_ENGINEER) + && (this->units[unitID].resourceToDeposit != 0)) { + _damage = _damage / 0x14; + } else if (_entityType == OpenSHC::Map::Entities::ET_BALLISTA) { + _damage = _damage / 2; + } else { + _damage = _damage / 3; + } + } + _unitHealth_ptr = &this->units[unitID].health; + *_unitHealth_ptr = *_unitHealth_ptr - _damage; + if (this->units[unitID].health < 1) { + this->units[unitID].health = 0; + } + if (_entityShootingUnitID_2 != 0) { + sVar3 = this->units[unitID].field97_0xd0; + if (sVar3 < 1000) { + this->units[unitID].field97_0xd0 = sVar3 + 200; + } + short* psVar1 = &DAT_TribesState::instance.tribes[_unknown].someUnitArrayIndex; + *psVar1 = *psVar1 + 1; + sVar3 = DAT_TribesState::instance.tribes[_unknown].someUnitArrayIndex; + DAT_TribesState::instance.tribes[_unknown].countdown = 100; + if (9 < sVar3) { + DAT_TribesState::instance.tribes[_unknown].someUnitArrayIndex = 0; + } + DAT_TribesState::instance.tribes[_unknown] + .someUnitArray[DAT_TribesState::instance.tribes[_unknown].someUnitArrayIndex] + = _entityShootingUnitID; + DAT_TribesState::instance.tribes[_unknown] + .someUnitUIDArray[DAT_TribesState::instance.tribes[_unknown].someUnitArrayIndex] + = this->units[_entityShootingUnitID_2].uid; + } + int _unitHealth = this->units[unitID].health; + _healthPercentage_2 + = MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::DirectionAlgorithmState_Func::computeHealthPercentage, + DAT_DirectionAlgorithmState::ptr)(_unitHealth, this->units[unitID].maxHealth); + _entityShootingUnitID = (short)_healthPercentage_2; + this->units[unitID].healthPercentage = _entityShootingUnitID; + this->units[unitID].healthbar = (_entityShootingUnitID / 10 + (_entityShootingUnitID >> 0xf)) + - (short)((longlong)(int)_entityShootingUnitID * 0x66666667 >> 0x3f); + if ((((_unitType == OpenSHC::Map::Units::UT_BREWER) || (_unitType == OpenSHC::Map::Units::UT_TANNER)) + || (_unitType == OpenSHC::Map::Units::UT_LADY)) + || ((_unitType == OpenSHC::Map::Units::UT_MOTHER + || ((_unitType == OpenSHC::Map::Units::UT_CHILD && (this->units[unitID].spriteID == 0x81)))))) { + bVar4 = true; + } + bool _shootingUnitID = this->units[_entityShootingUnitID_2].unitType == OpenSHC::Map::Units::UT_A_SLINGER; + if ((_unitHealth < 1) && (this->units[unitID].dying == 0)) { + this->units[unitID].dying = 1; + if (0 < _unknown) { + DAT_TribesState::instance.tribes[_unknown].field133_0x278 = 1; + } + this->units[unitID].animationCycleNumber = 0; + _entityType = DAT_EntityState::instance.entityArray[entityID].entityType; + if (_entityType == OpenSHC::Map::Entities::ET_COW_FLYING) { + this->units[unitID].state.generic = OpenSHC::Map::Units::States::US_STONE_DEATH_01; + } else { + this->units[unitID].state.generic + = (-(ushort)(_entityType != OpenSHC::Map::Entities::ET_SLINGER) & 0xfffd) + + OpenSHC::Map::Units::States::US_STONE_DEATH_01; + } + byte bVar2 = this->units[unitID].isStalked; + this->units[unitID].tunnelerFinishedDigging = 1; + if (bVar2 == 0) { + switch (this->units[unitID].unitType) { + case OpenSHC::Map::Units::UT_S_CATAPULT: + case OpenSHC::Map::Units::UT_S_MANGONEL: + case OpenSHC::Map::Units::UT_S_TOWER: + case OpenSHC::Map::Units::UT_S_BATTERINGRAM: + case OpenSHC::Map::Units::UT_S_BALLISTA: + case OpenSHC::Map::Units::UT_S_FBALLISTA: + sfxOffsetInArray = OpenSHC::DE::SHCDE::FX_SIEGE_DIE; + break; + case OpenSHC::Map::Units::UT_S_TREBUCHET: + MACRO_CALL_MEMBER(OpenSHC::Audio::SFX::SFXState_Func::playSFXAtLocation, DAT_SFXState::ptr)( + (int)this->units[unitID].x, (int)((int)(this->units[unitID].y)), + OpenSHC::DE::SHCDE::FX_TR_DIE); + break; + case OpenSHC::Map::Units::UT_S_SHIELD: + if ((this->units[unitID].digTileX__OR__countCurrentlyManningEnginers__OR__forCowsRandomBelow300 + != 0) + && (!_shootingUnitID)) { + sfxOffsetInArray = OpenSHC::DE::SHCDE::FX_DEATH_ARROW; + break; + } + sfxOffsetInArray = OpenSHC::DE::SHCDE::FX_SIEGE_DIE; + break; + } + if (bVar4) { + MACRO_CALL_MEMBER(OpenSHC::Audio::SFX::SFXState_Func::playSFXAtLocation, DAT_SFXState::ptr)( + this->units[unitID].x, this->units[unitID].y, OpenSHC::DE::SHCDE::FX_GIRL_DIE); + if (_shootingUnitID) { + sfxOffsetInArray = OpenSHC::DE::SHCDE::FX_HIT_SLINGSTONE; + } else { + sfxOffsetInArray = OpenSHC::DE::SHCDE::FX_ARROW_HIT; + } + } else if (!_shootingUnitID) { + sfxOffsetInArray = OpenSHC::DE::SHCDE::FX_DEATH_ARROW; + } else { + sfxOffsetInArray = OpenSHC::DE::SHCDE::FX_DEATH_SLINGSTONE; + } + } else if (_shootingUnitID) { + sfxOffsetInArray = OpenSHC::DE::SHCDE::FX_HIT_SLINGSTONE; + } else { + sfxOffsetInArray = OpenSHC::DE::SHCDE::FX_ARROW_HIT_ANIMAL; + } + } else { + if (this->units[unitID].isStalked != 0) { + if (_shootingUnitID) { + sfxOffsetInArray = OpenSHC::DE::SHCDE::FX_HIT_SLINGSTONE; + } else { + sfxOffsetInArray = OpenSHC::DE::SHCDE::FX_ARROW_HIT_ANIMAL; + } + } else { + switch (this->units[unitID].unitType) { + case OpenSHC::Map::Units::UT_S_CATAPULT: + case OpenSHC::Map::Units::UT_S_TREBUCHET: + case OpenSHC::Map::Units::UT_S_MANGONEL: + case OpenSHC::Map::Units::UT_S_TOWER: + case OpenSHC::Map::Units::UT_S_BATTERINGRAM: + case OpenSHC::Map::Units::UT_S_BALLISTA: + case OpenSHC::Map::Units::UT_S_FBALLISTA: + sfxOffsetInArray = OpenSHC::DE::SHCDE::FX_WOOD_HIT; + break; + default: + uVar5 = this->units[unitID].fixedRng & 7; + if (uVar5 != 0) { + if (uVar5 == 1) + sfxOffsetInArray = OpenSHC::DE::SHCDE::FX_BODY_HIT2; + break; + if (uVar5 == 2) { + sfxOffsetInArray = OpenSHC::DE::SHCDE::FX_BODY_HIT3; + break; + } + if (uVar5 == 3) { + sfxOffsetInArray = OpenSHC::DE::SHCDE::FX_BODY_HIT4; + break; + } + if (uVar5 == 4) { + sfxOffsetInArray = OpenSHC::DE::SHCDE::FX_BODY_HIT5; + } else { + if (uVar5 == 5) { + sfxOffsetInArray = OpenSHC::DE::SHCDE::FX_BODY_HIT6; + break; + } + if (uVar5 == 6) { + sfxOffsetInArray = OpenSHC::DE::SHCDE::FX_BODY_HIT7; + break; + } + if (uVar5 != 7) { + return TRUE; + } + sfxOffsetInArray = OpenSHC::DE::SHCDE::FX_BODY_HIT8; + } + break; + } + sfxOffsetInArray = OpenSHC::DE::SHCDE::FX_BODY_HIT; + break; + case OpenSHC::Map::Units::UT_LORD: + return TRUE; + case OpenSHC::Map::Units::UT_S_SHIELD: + if (this->units[unitID].digTileX__OR__countCurrentlyManningEnginers__OR__forCowsRandomBelow300 + < 1) { + return TRUE; + } + } + } + } + MACRO_CALL_MEMBER(OpenSHC::Audio::SFX::SFXState_Func::playSFXAtLocation, DAT_SFXState::ptr)( + _unitXPosition_2, _unitYPosition_2, sfxOffsetInArray); + return TRUE; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 984ae3bb8..f78e6d481 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -50075,7 +50075,7 @@ SHC_3BB0A8C1_0x00531914 | 0.0% | Pending SHC_3BB0A8C1_0x00531915 | 0.0% | Pending -SHC_3BB0A8C1_0x00531920 | 0.0% | Pending +SHC_3BB0A8C1_0x00531920 | 18.0% | orig merges pos blocks SHC_3BB0A8C1_0x005323C0 | 0.0% | Pending From c9a19fe62436985d0e9be204665ea0328bc264aa Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 10:46:44 +0200 Subject: [PATCH 193/299] reimplement: SHC_3BB0A8C1_0x0054B0D0 38.11% score tail, reg alloc --- .../Units/UnitsState/acquireShootTarget.cpp | 607 ++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 608 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/acquireShootTarget.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/acquireShootTarget.cpp b/src/OpenSHC/Map/Units/UnitsState/acquireShootTarget.cpp new file mode 100644 index 000000000..c8d6a30e9 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/acquireShootTarget.cpp @@ -0,0 +1,607 @@ +#include "OpenSHC/Map/Entities/EntityState.func.hpp" +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Rendering/ViewportRenderState.func.hpp" +#include "OpenSHC/Map/Units/States/UnitState.hpp" +#include "OpenSHC/Map/Units/UnitInstructionType.hpp" +#include "OpenSHC/Map/Units/UnitLogicState.hpp" +#include "OpenSHC/Map/Units/UnitType.hpp" +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_EntityDefinedData.hpp" +#include "OpenSHC/Globals/DAT_EntityState.hpp" +#include "OpenSHC/Globals/DAT_GameState.hpp" +#include "OpenSHC/Globals/DAT_GameSynchronyState.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_TribesState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Map::Units::UnitInstructionType; + using OpenSHC::Map::Units::UnitLogicState; + using OpenSHC::Map::Units::UnitType; + using OpenSHC::Map::Units::States::UnitState; + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x0054B0D0 + BOOLEnum UnitsState::acquireShootTarget(int unitID) + + { + short* psVar1; + UnitTypeShort UVar4; + short sVar5; + int _unitTotalHeight; + int _rangeSquared; + BOOLEnum BVar6; + int iVar7; + short sVar9; + int _xDifferenceToTarget; + int _0x04_yDifference; + int _yDifferenceToTarget; + int _entityType; + int local_30; + int local_2c; + int _validTargetID; + int local_10; + int local_c; + int local_8; + short _unitID_2; + int _unitID; + + _unitID = unitID; + int _unitPlayerID = (int)this->units[unitID].owner; + int _microXUnit = (int)this->units[unitID].microXPosition; + int _microYUnit = (int)this->units[unitID].microYPosition; + _unitTotalHeight = (int)this->units[unitID].buildingHeight + (int)this->units[unitID].terrainOrClimbHeight; + _validTargetID = 0; + local_30 = 100000; + local_8 = 0; + local_2c = 100000; + local_10 = 0; + local_c = 0; + /* + switch based on unit type + */ + + switch (this->units[unitID].unitType) { + case OpenSHC::Map::Units::UT_E_XBOW: + /* + crossbow + */ + + _entityType = 7; + break; + default: + /* + default: + */ + + _entityType = 1; + break; + case OpenSHC::Map::Units::UT_S_CATAPULT: + /* + catapult + */ + + _entityType = 2; + if ((this->units[unitID].stoneAmmunition < 1) + && (this->units[unitID].targetingType != OpenSHC::Map::Units::UIT_THROW_COW)) { + this->units[unitID].targetingType = OpenSHC::Map::Units::UIT_NO_INSTRUCTION_OR_MOVEUnk; + return FALSE; + } + break; + case OpenSHC::Map::Units::UT_S_TREBUCHET: + /* + trebuchet + */ + + _entityType = 3; + if ((this->units[unitID].stoneAmmunition < 1) + && (this->units[unitID].targetingType != OpenSHC::Map::Units::UIT_THROW_COW)) { + this->units[unitID].targetingType = OpenSHC::Map::Units::UIT_NO_INSTRUCTION_OR_MOVEUnk; + return FALSE; + } + break; + case OpenSHC::Map::Units::UT_S_MANGONEL: + /* + mangonel + */ + + _entityType = 4; + break; + case OpenSHC::Map::Units::UT_S_BALLISTA: + /* + ballista + */ + + _entityType = 0x14; + break; + case OpenSHC::Map::Units::UT_A_SLINGER: + /* + slinger + */ + + _entityType = 0x21; + break; + case OpenSHC::Map::Units::UT_A_FIRETHROWER: + /* + fire thrower + */ + + _entityType = 0x22; + break; + case OpenSHC::Map::Units::UT_S_FBALLISTA: + /* + fire ballista + */ + + _entityType = 0x25; + } + _rangeSquared = DAT_EntityDefinedData::instance.EntityTypeArrayForProjectileRange[_entityType] + * DAT_EntityDefinedData::instance.EntityTypeArrayForProjectileRange[_entityType]; + /* + fetch attacking explicitness + */ + + if (this->units[unitID].targetingType == OpenSHC::Map::Units::UIT_UNIT_ATTACK_UNIT) { + /* + if explicitness = 4 (user selected attack)... + fetch the targetedUnitID + */ + + sVar9 = this->units[unitID].targetedUnitID__OR__engineerMannedSiegeEngineRef; + int _0x04_targetUnitID = (int)sVar9; + if (((((this->units[_0x04_targetUnitID].uid + == this->units[unitID] + .targetedUnitUIDUnk_OR_someAppearTileUnk_OR_buildingUID_OR_pitchDitchUID_OR_entityUID) + && (this->units[_0x04_targetUnitID].dying == 0)) + && (this->units[_0x04_targetUnitID].logicalState == OpenSHC::Map::Units::ULS_NORMAL)) + && ((BVar6 = MACRO_CALL_MEMBER( + OpenSHC::Map::Units::UnitsState_Func::checkIfCitizenUnitIsAliveBasedOnState, this)( + _0x04_targetUnitID), + BVar6 == FALSE + && (this->units[_0x04_targetUnitID].state.generic + != (OpenSHC::Map::Units::States::US_STONE_DEATH_03 + | OpenSHC::Map::Units::States::US_IDLEUnk))))) + && (DAT_GameState::instance.mapAndTime.playerTeams[this->units[_0x04_targetUnitID].owner] + != DAT_GameState::instance.mapAndTime.playerTeams[_unitPlayerID])) { + psVar1 = &this->units[_0x04_targetUnitID].microYPosition; + short* psVar2 = &this->units[_0x04_targetUnitID].microXPosition; + _0x04_yDifference = ((int)(_microYUnit + (_microYUnit >> 0x1f & 7U)) >> 3) + - ((int)((int)*psVar1 + ((int)*psVar1 >> 0x1f & 7U)) >> 3); + _xDifferenceToTarget = ((int)(_microXUnit + (_microXUnit >> 0x1f & 7U)) >> 3) + - ((int)((int)*psVar2 + ((int)*psVar2 >> 0x1f & 7U)) >> 3); + if (_xDifferenceToTarget * _xDifferenceToTarget + _0x04_yDifference * _0x04_yDifference + <= _rangeSquared) { + short* psVar3 = &this->units[_0x04_targetUnitID].terrainOrClimbHeight; + _unitID = MACRO_CALL_MEMBER(OpenSHC::Map::Entities::EntityState_Func::arrowShootingRelated, + DAT_EntityState::ptr)(_microXUnit, _microYUnit, _unitTotalHeight + 0x1e, + (int)((int)(*psVar2)), (int)((int)(*psVar1)), + (int)((int)(this->units[_0x04_targetUnitID].buildingHeight + 0x1a + + this->units[_0x04_targetUnitID].terrainOrClimbHeight))); + if (((_unitID < 1) + || (UVar4 = this->units[unitID].unitType, UVar4 == OpenSHC::Map::Units::UT_S_MANGONEL)) + || (UVar4 == OpenSHC::Map::Units::UT_S_BALLISTA)) { + if (this->units[unitID].unitType == OpenSHC::Map::Units::UT_HUNTER) { + return FALSE; + } + this->units[unitID].shootTargetedUnit = -2; + this->units[unitID].shootTargetMicroX = *psVar2; + this->units[unitID].shootTargetMicroY = *psVar1; + this->units[unitID].shootTargetZ = *psVar3; + return TRUE; + } + this->units[unitID].shootTargetedUnit = sVar9; + this->units[unitID].targetUID = this->units[_0x04_targetUnitID].uid; + this->units[unitID].distanceToEnemyUnitLadders = (short)_unitID; + this->units[unitID].shootTargetMicroX = *psVar2; + this->units[unitID].shootTargetMicroY = *psVar1; + this->units[unitID].shootTargetZ = *psVar3; + if (100 < _unitID) { + this->units[unitID].jugglerCount = 0; + this->units[_0x04_targetUnitID].field233_0x39a = 1; + return TRUE; + } + _unitID = (int)*psVar3 + (int)this->units[_0x04_targetUnitID].buildingHeight; + _unitPlayerID + = (int)this->units[unitID].buildingHeight + (int)this->units[unitID].terrainOrClimbHeight; + if (_unitID + 0x46 < _unitPlayerID) { + this->units[unitID].jugglerCount = 1; + this->units[_0x04_targetUnitID].field233_0x39a = 1; + return TRUE; + } + this->units[unitID].jugglerCount = (_unitID + -0x46 <= _unitPlayerID) - 1; + this->units[_0x04_targetUnitID].field233_0x39a = 1; + return TRUE; + } + if (DAT_GameSynchronyState::instance.currentPlayerFullIDArray[this->units[unitID].owner] != -1) { + return FALSE; + } + } + /* + fixme + */ + + sVar9 = this->units[unitID]._someX_2; + /* + fixmefixme + */ + + this->units[unitID].targetedUnitID__OR__engineerMannedSiegeEngineRef = 0; + this->units[unitID].shootTargetedUnit = 0; + this->units[unitID].targetingType = OpenSHC::Map::Units::UIT_NO_INSTRUCTION_OR_MOVEUnk; + if (sVar9 != 0) { + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::setDestinationForUnit, this)( + unitID, (uint)((int)((int)sVar9)), (uint)((int)((int)this->units[unitID]._someY_2)), 0); + this->units[unitID]._someX_2 = 0; + this->units[unitID]._someY_2 = 0; + this->units[unitID].moveDelay = 0; + this->units[unitID].targetedBuildingTile = 0; + this->units[unitID].state.generic = OpenSHC::Map::Units::States::US_MOVE_TO_DESTINATION; + return TRUE; + } + } + if (this->units[unitID].targetingType == OpenSHC::Map::Units::UIT_LIGHT_PITCH) { + /* + get the workplace building id + */ + + sVar9 = this->units[unitID].targetID_OR_targetBuildingID; + if ((DAT_TileMapState::instance.pitchDitches[sVar9].uid + == this->units[unitID] + .targetedUnitUIDUnk_OR_someAppearTileUnk_OR_buildingUID_OR_pitchDitchUID_OR_entityUID) + && (_unitID = MACRO_CALL_MEMBER(OpenSHC::Map::Entities::EntityState_Func::isBrazierNearby, + DAT_EntityState::ptr)((int)this->units[unitID].x, (int)((int)(this->units[unitID].y)), + (int)(( + int)(this->units[unitID].buildingHeight + this->units[unitID].terrainOrClimbHeight))), + _unitID != 0)) { + this->units[unitID].shootTargetMicroX = DAT_TileMapState::instance.pitchDitches[sVar9].x * 8 + 4; + this->units[unitID].shootTargetMicroY = DAT_TileMapState::instance.pitchDitches[sVar9].y * 8 + 4; + this->units[unitID].shootTargetZ + = (ushort)DAT_TileMapState::instance + .HeightLayer[DAT_TileMapState::instance.pitchDitches[sVar9].tile]; + this->units[unitID].shootTargetedUnit = -1; + return TRUE; + } + } else if (this->units[unitID].targetingType == OpenSHC::Map::Units::UIT_ATTACK_BUILDING) { + sVar9 = this->units[unitID].targetID_OR_targetBuildingID; + if (DAT_BuildingsState::instance.buildings[sVar9].uid + == this->units[unitID] + .targetedUnitUIDUnk_OR_someAppearTileUnk_OR_buildingUID_OR_pitchDitchUID_OR_entityUID) { + this->units[unitID].shootTargetMicroX = DAT_BuildingsState::instance.buildings[sVar9].x * 8 + + (short)((int)(DAT_BuildingsState::instance.buildings[sVar9].widthOrHeight * 8) / 2); + this->units[unitID].shootTargetMicroY = DAT_BuildingsState::instance.buildings[sVar9].y * 8 + + (short)((int)(DAT_BuildingsState::instance.buildings[sVar9].widthOrHeight * 8) / 2); + this->units[unitID].shootTargetZ = DAT_BuildingsState::instance.buildings[sVar9].terrainHeightUnk; + this->units[unitID].shootTargetedUnit = -1; + return TRUE; + } + } else if (this->units[unitID].targetingType == OpenSHC::Map::Units::UIT_ATTACK_WALL) { + int _0x17_y = (int)this->units[unitID].attackAtTileY; + int _0x17_x = (int)this->units[unitID].attackAtTileX; + int _0x17_tile = DAT_ViewportRenderState::instance.translationMatrix[_0x17_y].addXgetTile + _0x17_x; + BVar6 = MACRO_CALL_MEMBER(OpenSHC::Rendering::ViewportRenderState_Func::xyAreValid, + DAT_ViewportRenderState::ptr)(_0x17_x, (uint)((int)(_0x17_y))); + if ((BVar6 != FALSE) && ((DAT_TileMapState::instance.LogicLayer[_0x17_tile] & 0x100U) != 0)) { + this->units[unitID].shootTargetMicroX = this->units[unitID].attackAtTileX * 8; + this->units[unitID].shootTargetMicroY = this->units[unitID].attackAtTileY * 8; + this->units[unitID].shootTargetZ + = (short)((int)((uint)DAT_TileMapState::instance.HeightLayer[_0x17_tile] + - (uint)DAT_TileMapState::instance.DefaultHeightLayer[_0x17_tile]) + / 2) + + (ushort)DAT_TileMapState::instance.DefaultHeightLayer[_0x17_tile]; + this->units[unitID].shootTargetedUnit = -1; + return TRUE; + } + } else { + if ((this->units[unitID].targetingType != OpenSHC::Map::Units::UIT_ATTACK_LAND) + && (this->units[unitID].targetingType != OpenSHC::Map::Units::UIT_THROW_COW)) { + if (_entityType == 2) { + return FALSE; + } + if (_entityType == 3) { + return FALSE; + } + for (int local_24 = 0; local_24 < DAT_GameState::instance.playerDataArray[_unitPlayerID].enemies; + local_24 = local_24 + 1) { + int _enemy = (int)*(short*)(_unitPlayerID * 0x39f4 + 0x115caf8 + local_24 * 2); + if ((this->units[_enemy].dying != 0) + || (this->units[_enemy].uid != *(int*)(_unitPlayerID * 10000 + 0x11a66f0 + local_24 * 4))) + continue; + switch (this->units[_enemy].unitType) { + case OpenSHC::Map::Units::UT_ANTELOPESHDEER: + if (this->units[_unitID].unitType != OpenSHC::Map::Units::UT_HUNTER) + continue; + break; + case OpenSHC::Map::Units::UT_LIONSHWOLF: + sVar9 = this->units[_enemy].tribeID; + if ((DAT_TribesState::instance.tribes[sVar9].unknownBool02 != 0) + || ((DAT_TribesState::instance.tribes[sVar9].unknownBool01 == 0 + && ((this->units[_enemy].state.generic != 0xcf + || (this->units[this->units[_enemy] + .targetedUnitID__OR__engineerMannedSiegeEngineRef] + .isStalked + != 0)))))) + continue; + break; + case OpenSHC::Map::Units::UT_RABBIT: + _xDifferenceToTarget = (int)this->units[_unitID].tribeID; + if (((this->units[_unitID].unitType == OpenSHC::Map::Units::UT_HUNTER) + || (_xDifferenceToTarget < 1)) + || (DAT_TribesState::instance.tribes[_xDifferenceToTarget].field71_0x212 == 0)) + continue; + break; + case OpenSHC::Map::Units::UT_CAGEDOG: + if (DAT_GameState::instance.mapAndTime.playerTeams[this->units[_enemy].displayColorPlayerID] + == DAT_GameState::instance.mapAndTime.playerTeams[this->units[_unitID].owner]) + continue; + break; + case OpenSHC::Map::Units::UT_A_ASSASSIN: + if (160 < this->units[_enemy].assassinsMicroDistanceToEnemyUnk) + continue; + } + _xDifferenceToTarget = (int)this->units[_enemy].microYPosition; + iVar7 = (int)this->units[_enemy].microXPosition; + _yDifferenceToTarget = ((int)(_microYUnit + (_microYUnit >> 0x1f & 7U)) >> 3) + - ((int)(_xDifferenceToTarget + (_xDifferenceToTarget >> 0x1f & 7U)) >> 3); + _xDifferenceToTarget = ((int)(_microXUnit + (_microXUnit >> 0x1f & 7U)) >> 3) + - ((int)(iVar7 + (iVar7 >> 0x1f & 7U)) >> 3); + if (_rangeSquared + < _xDifferenceToTarget * _xDifferenceToTarget + _yDifferenceToTarget * _yDifferenceToTarget) + continue; + _xDifferenceToTarget = (int)this->units[_enemy].microXPosition; + if (_xDifferenceToTarget < _microXUnit) { + _xDifferenceToTarget = _microXUnit - _xDifferenceToTarget; + } else { + _xDifferenceToTarget = _xDifferenceToTarget - _microXUnit; + } + iVar7 = (int)this->units[_enemy].microYPosition; + if (iVar7 < _microYUnit) { + _yDifferenceToTarget = _microYUnit - iVar7; + } else { + _yDifferenceToTarget = iVar7 - _microYUnit; + } + if (_xDifferenceToTarget < _yDifferenceToTarget) { + _xDifferenceToTarget = _yDifferenceToTarget; + } + _xDifferenceToTarget = _xDifferenceToTarget + this->units[_enemy].field265_0x3dc * 0x32; + bool _scoreNeedsValidityCheck; + if (_entityType == 4) { + switch (this->units[_enemy].unitType) { + case OpenSHC::Map::Units::UT_E_ENGINEER: + case OpenSHC::Map::Units::UT_S_CATAPULT: + case OpenSHC::Map::Units::UT_S_TREBUCHET: + case OpenSHC::Map::Units::UT_S_MANGONEL: + 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_S_BALLISTA: + case OpenSHC::Map::Units::UT_S_FBALLISTA: + break; + default: + if (DAT_GameSynchronyState::instance + .currentPlayerFullIDArray[this->units[_unitID].owner] + != -1) + continue; + if (this->units[_enemy].isSelectable_OR_matchTime == 0) { + _xDifferenceToTarget = (_xDifferenceToTarget * 5 + 0x32) * 2; + } else { + _xDifferenceToTarget = _xDifferenceToTarget * 3 + 100; + } + } + _scoreNeedsValidityCheck = true; + } else if (_entityType == 0x14) { + switch (this->units[_enemy].unitType) { + case OpenSHC::Map::Units::UT_E_ARCHER: + case OpenSHC::Map::Units::UT_E_XBOW: + case OpenSHC::Map::Units::UT_E_SPEAR: + case OpenSHC::Map::Units::UT_E_MACE: + case OpenSHC::Map::Units::UT_E_LADDER: + case OpenSHC::Map::Units::UT_A_ARCHER: + case OpenSHC::Map::Units::UT_A_SLAVE: + case OpenSHC::Map::Units::UT_A_SLINGER: + case OpenSHC::Map::Units::UT_A_ASSASSIN: + case OpenSHC::Map::Units::UT_A_HARCHER: + _xDifferenceToTarget = _xDifferenceToTarget * 5 + 200; + 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_SWORDSMAN: + break; + case OpenSHC::Map::Units::UT_E_ENGINEER: + case OpenSHC::Map::Units::UT_S_CATAPULT: + case OpenSHC::Map::Units::UT_S_TREBUCHET: + case OpenSHC::Map::Units::UT_S_MANGONEL: + case OpenSHC::Map::Units::UT_LORD: + 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_S_BALLISTA: + case OpenSHC::Map::Units::UT_A_FIRETHROWER: + case OpenSHC::Map::Units::UT_S_FBALLISTA: + _xDifferenceToTarget = _xDifferenceToTarget * 2 + 100; + break; + default: + _xDifferenceToTarget = (_xDifferenceToTarget * 5 + 200) * 2; + } + _scoreNeedsValidityCheck = false; + } else if (_entityType != 0x25) { + if ((this->units[_enemy].field289_0x3ff != 0) + && (DAT_GameSynchronyState::instance.currentPlayerFullIDArray[this->units[_enemy].owner] + == -1)) { + _xDifferenceToTarget = _xDifferenceToTarget / 3; + } + switch (this->units[_enemy].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: + _xDifferenceToTarget = _xDifferenceToTarget + 0x4b; + break; + case OpenSHC::Map::Units::UT_E_SPEAR: + case OpenSHC::Map::Units::UT_E_PIKE: + case OpenSHC::Map::Units::UT_E_MACE: + case OpenSHC::Map::Units::UT_E_SWORD: + case OpenSHC::Map::Units::UT_E_KNIGHT: + case OpenSHC::Map::Units::UT_A_SLAVE: + case OpenSHC::Map::Units::UT_A_SLINGER: + case OpenSHC::Map::Units::UT_A_ASSASSIN: + case OpenSHC::Map::Units::UT_A_SWORDSMAN: + _xDifferenceToTarget = _xDifferenceToTarget * 5 + 200; + break; + case OpenSHC::Map::Units::UT_E_LADDER: + _xDifferenceToTarget = _xDifferenceToTarget * 7 + 300; + break; + case OpenSHC::Map::Units::UT_E_ENGINEER: + case OpenSHC::Map::Units::UT_S_CATAPULT: + case OpenSHC::Map::Units::UT_S_TREBUCHET: + case OpenSHC::Map::Units::UT_LORD: + _xDifferenceToTarget = _xDifferenceToTarget * 2 + 100; + break; + default: + _xDifferenceToTarget = (_xDifferenceToTarget * 5 + 200) * 2; + break; + case OpenSHC::Map::Units::UT_S_MANGONEL: + case OpenSHC::Map::Units::UT_S_BALLISTA: + case OpenSHC::Map::Units::UT_A_FIRETHROWER: + case OpenSHC::Map::Units::UT_S_FBALLISTA: + break; + } + _scoreNeedsValidityCheck = false; + } else { + switch (this->units[_enemy].unitType) { + case OpenSHC::Map::Units::UT_E_ARCHER: + case OpenSHC::Map::Units::UT_E_XBOW: + case OpenSHC::Map::Units::UT_E_SPEAR: + case OpenSHC::Map::Units::UT_E_MACE: + case OpenSHC::Map::Units::UT_E_LADDER: + case OpenSHC::Map::Units::UT_A_ARCHER: + case OpenSHC::Map::Units::UT_A_SLAVE: + case OpenSHC::Map::Units::UT_A_SLINGER: + case OpenSHC::Map::Units::UT_A_ASSASSIN: + case OpenSHC::Map::Units::UT_A_HARCHER: + _xDifferenceToTarget = _xDifferenceToTarget * 5 + 200; + 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_SWORDSMAN: + break; + case OpenSHC::Map::Units::UT_E_ENGINEER: + case OpenSHC::Map::Units::UT_S_CATAPULT: + case OpenSHC::Map::Units::UT_S_TREBUCHET: + case OpenSHC::Map::Units::UT_S_MANGONEL: + 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_S_BALLISTA: + case OpenSHC::Map::Units::UT_A_FIRETHROWER: + case OpenSHC::Map::Units::UT_S_FBALLISTA: + _xDifferenceToTarget = _xDifferenceToTarget * 2 + 100; + break; + default: + continue; + case OpenSHC::Map::Units::UT_LORD: + if (DAT_GameSynchronyState::instance.currentPlayerFullIDArray[_unitPlayerID] != -1) + _xDifferenceToTarget = _xDifferenceToTarget * 5 + 200; + break; + } + _scoreNeedsValidityCheck = true; + } + if (!_scoreNeedsValidityCheck || _xDifferenceToTarget != -1) { + if (((_xDifferenceToTarget < local_30) || (_xDifferenceToTarget < local_2c)) + && (iVar7 + = MACRO_CALL_MEMBER(OpenSHC::Map::Entities::EntityState_Func::arrowShootingRelated, + DAT_EntityState::ptr)(_microXUnit, _microYUnit, _unitTotalHeight + 0x1e, + (int)((int)(this->units[_enemy].microXPosition)), iVar7, + (int)((int)(this->units[_enemy].buildingHeight + 0x1a + + this->units[_enemy].terrainOrClimbHeight))), + 0 < iVar7)) { + if (_xDifferenceToTarget < local_30) { + local_30 = _xDifferenceToTarget; + _validTargetID = _enemy; + local_8 = iVar7; + } + if ((this->units[_enemy].field233_0x39a == 0) && (_xDifferenceToTarget < local_2c)) { + local_2c = _xDifferenceToTarget; + local_10 = _enemy; + local_c = iVar7; + } + } + } + } + if (_validTargetID == 0) { + return FALSE; + } + if ((local_10 != 0) && (local_2c < (local_30 * 3) / 2)) { + _validTargetID = local_10; + local_8 = local_c; + } + if (_entityType == 4) { + this->units[_unitID].shootTargetedUnit = -2; + this->units[_unitID].shootTargetMicroX = this->units[_validTargetID].microXPosition; + this->units[_unitID].shootTargetMicroY = this->units[_validTargetID].microYPosition; + this->units[_unitID].shootTargetZ = this->units[_validTargetID].terrainOrClimbHeight; + return TRUE; + } + sVar9 = (short)_validTargetID; + if ((_entityType == 0x25) || (_entityType == 0x14)) { + this->units[_unitID].shootTargetedUnit = sVar9; + this->units[_unitID].targetUID = this->units[_validTargetID].uid; + this->units[_unitID].distanceToEnemyUnitLadders = (short)local_8; + this->units[_unitID].shootTargetMicroX = this->units[_validTargetID].microXPosition; + this->units[_unitID].shootTargetMicroY = this->units[_validTargetID].microYPosition; + this->units[_unitID].shootTargetZ = this->units[_validTargetID].terrainOrClimbHeight; + return TRUE; + } + psVar1 = &this->units[_validTargetID].field265_0x3dc; + *psVar1 = *psVar1 + 1; + this->units[_unitID].shootTargetedUnit = sVar9; + this->units[_unitID].field266_0x3de = sVar9; + this->units[_unitID].targetUID = this->units[_validTargetID].uid; + this->units[_unitID].distanceToEnemyUnitLadders = (short)local_8; + if (100 < local_8) { + this->units[_unitID].jugglerCount = 0; + this->units[_validTargetID].field233_0x39a = 1; + return TRUE; + } + _unitPlayerID = (int)this->units[_validTargetID].terrainOrClimbHeight + + (int)this->units[_validTargetID].buildingHeight; + _microXUnit + = (int)this->units[_unitID].buildingHeight + (int)this->units[_unitID].terrainOrClimbHeight; + if (_unitPlayerID + 0x46 < _microXUnit) { + this->units[_unitID].jugglerCount = 1; + this->units[_validTargetID].field233_0x39a = 1; + return TRUE; + } + this->units[_unitID].jugglerCount = (_unitPlayerID + -0x46 <= _microXUnit) - 1; + this->units[_validTargetID].field233_0x39a = 1; + return TRUE; + } + sVar9 = this->units[unitID].attackAtTileY; + sVar5 = this->units[unitID].attackAtTileX; + this->units[unitID].jugglerCount = -1; + BVar6 = MACRO_CALL_MEMBER(OpenSHC::Rendering::ViewportRenderState_Func::xyAreValid, + DAT_ViewportRenderState::ptr)((int)sVar5, (uint)((int)((int)sVar9))); + if (BVar6 != FALSE) { + sVar5 = this->units[unitID].attackAtTileX; + this->units[unitID].shootTargetMicroX = sVar5 * 8; + this->units[unitID].shootTargetedUnit = -1; + this->units[unitID].shootTargetMicroY = sVar9 * 8; + this->units[unitID].shootTargetZ = (ushort) + * (byte*)(DAT_ViewportRenderState::instance.translationMatrix[sVar9].addXgetTile + 0x1d32c38 + + (int)sVar5); + return TRUE; + } + } + this->units[unitID].targetingType = OpenSHC::Map::Units::UIT_NO_INSTRUCTION_OR_MOVEUnk; + return FALSE; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index f78e6d481..bee03eb15 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -61833,7 +61833,7 @@ SHC_3BB0A8C1_0x0054B0CB | 0.0% | Pending SHC_3BB0A8C1_0x0054B0CC | 0.0% | Pending -SHC_3BB0A8C1_0x0054B0D0 | 0.0% | Pending +SHC_3BB0A8C1_0x0054B0D0 | 38.1% | score tail, reg alloc SHC_3BB0A8C1_0x0054BE04 | 0.0% | Pending From 6b4b47edb519bee4d3f99077b11fca511c0329cd Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 10:54:24 +0200 Subject: [PATCH 194/299] reimplement: SHC_3BB0A8C1_0x00579300 28.52% reg alloc, dup tails --- .../Map/Units/UnitsState/updateUnits.cpp | 935 ++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 936 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/updateUnits.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/updateUnits.cpp b/src/OpenSHC/Map/Units/UnitsState/updateUnits.cpp new file mode 100644 index 000000000..25b8e95ae --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/updateUnits.cpp @@ -0,0 +1,935 @@ +#include "OpenSHC/Audio/SFX/SFXState.func.hpp" +#include "OpenSHC/IO/LowLevelMemory.func.hpp" +#include "OpenSHC/Map/Entities/EntityState.func.hpp" +#include "OpenSHC/Map/Units/TroopValueState.func.hpp" +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/DE/SHCDE/eSFX.hpp" +#include "OpenSHC/Map/Buildings/BuildingLogicalState.hpp" +#include "OpenSHC/Map/Buildings/BuildingType.hpp" +#include "OpenSHC/Map/Units/Pathfinding/DestinationNeededEnum.hpp" +#include "OpenSHC/Map/Units/States/UnitState.hpp" +#include "OpenSHC/Map/Units/UnitInstructionType.hpp" +#include "OpenSHC/Map/Units/UnitLogicState.hpp" +#include "OpenSHC/Map/Units/UnitType.hpp" +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +#include "OpenSHC/Globals/DAT_BuildingDefinedData.hpp" +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_CurrentUnitSlotID.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_SFXState.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_TroopValueState.hpp" +#include "OpenSHC/Globals/DAT_UnitHasBecomeIdle.hpp" +#include "OpenSHC/Globals/DAT_UnitPropertiesDefinedData.hpp" +#include "OpenSHC/Globals/DAT_UpdateUnitsTracker.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" +#include "OpenSHC/Globals/SEC_RNG.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::DE::SHCDE::eSFX; + using OpenSHC::Map::Buildings::BuildingLogicalState; + using OpenSHC::Map::Buildings::BuildingType; + using OpenSHC::Map::Buildings::BuildingTypeShort; + using OpenSHC::Map::Units::UnitInstructionType; + using OpenSHC::Map::Units::UnitLogicState; + using OpenSHC::Map::Units::UnitType; + using OpenSHC::Map::Units::Pathfinding::DestinationNeededEnum; + using OpenSHC::Map::Units::States::UnitState; + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x00579300 + void UnitsState::updateUnits() + + { + int* piVar1; + short* psVar4; + UnitTypeShort UVar6; + uint _unitIDBased8value; + uint uVar9; + int _troopValue; + byte bVar13; + uint _rngNumber8; + uint _unitID; + uint _currentUnitID; + UnitTypeShort _unitType; + short _buildingID; + BuildingTypeShort _buildingType; + + _rngNumber8 = (int)SEC_RNG::instance.currentNumber2 & 0x8000000f; + if ((int)_rngNumber8 < 0) { + _rngNumber8 = (_rngNumber8 - 1 | 0xfffffff0) + 1; + } + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 80400, '\0', (void*)((int)(DAT_TileMapState::instance.OccupancyLayer))); + DAT_GameState::instance.playerDataArray[0].healerCount = 0; + DAT_GameState::instance.playerDataArray[1].healerCount = 0; + DAT_GameState::instance.playerDataArray[2].healerCount = 0; + DAT_GameState::instance.playerDataArray[3].healerCount = 0; + DAT_GameState::instance.playerDataArray[4].healerCount = 0; + DAT_GameState::instance.playerDataArray[5].healerCount = 0; + DAT_GameState::instance.playerDataArray[6].healerCount = 0; + DAT_GameState::instance.playerDataArray[7].healerCount = 0; + DAT_GameState::instance.playerDataArray[8].healerCount = 0; + this->unitCount = 0; + this->maxUnitCount = 0; + DAT_CurrentUnitSlotID::instance = 1; + do { + _currentUnitID = DAT_CurrentUnitSlotID::instance; + if (this->units[DAT_CurrentUnitSlotID::instance].logicalState != OpenSHC::Map::Units::ULS_INVISIBLE) { + this->maxUnitCount = DAT_CurrentUnitSlotID::instance + 1; + this->units[DAT_CurrentUnitSlotID::instance].field233_0x39a = 0; + this->units[DAT_CurrentUnitSlotID::instance].attackedBy = 0; + this->units[DAT_CurrentUnitSlotID::instance].huntedBy = 0; + this->units[DAT_CurrentUnitSlotID::instance].field265_0x3dc = 0; + this->units[DAT_CurrentUnitSlotID::instance].field43_0x64 = 0; + /* + This literally does nothing, this variable is not used elsewhere, what the + hell? + */ + + psVar4 = &this->units[DAT_CurrentUnitSlotID::instance].targetShootRelated; + if (this->units[DAT_CurrentUnitSlotID::instance].targetShootRelated != 0) { + *psVar4 = *psVar4 + -1; + } + uVar9 = DAT_CurrentUnitSlotID::instance; + if ((this->units[DAT_CurrentUnitSlotID::instance].state.generic + == OpenSHC::Map::Units::States::US_DETERMINE_NEXT_STATEUnk) + && (_troopValue + = MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::isUnitRegisteredOnItsOwnTile, + this)(DAT_CurrentUnitSlotID::instance), + _troopValue == 0)) { + this->lostChimps = this->lostChimps + 1; + this->units[DAT_CurrentUnitSlotID::instance].logicalState = OpenSHC::Map::Units::ULS_REMOVE; + uVar9 = DAT_CurrentUnitSlotID::instance; + } + _buildingID = this->units[uVar9].owner; + if (DAT_GameSynchronyState::instance.currentPlayerFullIDArray[_buildingID] == -1) { + this->units[uVar9].siegeTargetPlayerID + = (short)DAT_GameState::instance.playerDataArray[_buildingID].attackedPlayerID; + } else { + this->units[uVar9].siegeTargetPlayerID = 0; + } + if (this->units[DAT_CurrentUnitSlotID::instance].blessedAmount != 0) { + this->units[DAT_CurrentUnitSlotID::instance].blessedAmount + = this->units[DAT_CurrentUnitSlotID::instance].blessedAmount + -1; + DAT_GameState::instance.playerDataArray[_buildingID].blessedPeopleCountUnk + = DAT_GameState::instance.playerDataArray[_buildingID].blessedPeopleCountUnk + 1; + } else if (DAT_UnitPropertiesDefinedData::instance + .NotBlessableUnits[(short)this->units[DAT_CurrentUnitSlotID::instance].unitType] + == 0) { + DAT_GameState::instance.playerDataArray[_buildingID].unblessedPeopleCountUnk + = DAT_GameState::instance.playerDataArray[_buildingID].unblessedPeopleCountUnk + 1; + } + _currentUnitID = DAT_CurrentUnitSlotID::instance; + _unitIDBased8value = _currentUnitID & 0x8000000f; + if ((int)_unitIDBased8value < 0) { + _unitIDBased8value = (_unitIDBased8value - 1 | 0xfffffff0) + 1; + } + if (_unitIDBased8value == _rngNumber8) { + int _unitTile = this->units[_currentUnitID].tile; + if (((((DAT_TileMapState::instance.PathConnectionLayer[_unitTile] == 0) + && ((DAT_TileMapState::instance.LogicLayer[_unitTile] & 0x40000000U) == 0)) + && (this->units[_currentUnitID].moveRelatedFlag != 1)) + && ((_buildingID = DAT_TileMapState::instance.BuildingLayer[_unitTile], + _buildingID == 0 + || (((DAT_BuildingsState::instance.buildings[_buildingID].logicalState + == OpenSHC::Map::Buildings::BLS_NORMAL + && (_buildingType + = DAT_BuildingsState::instance.buildings[_buildingID].buildingType, + DAT_BuildingDefinedData::instance + .BuildingIsGateHouseArray[(short)_buildingType] + == 0)) + && (_buildingType != OpenSHC::Map::Buildings::BT_DRAWBRIDGE)))))) + && (this->units[_currentUnitID].state.generic + != OpenSHC::Map::Units::States::US_DISAPPEAR)) { + if (this->units[_currentUnitID].unitType == OpenSHC::Map::Units::UT_CHICKEN) { + MACRO_CALL_MEMBER(OpenSHC::Audio::SFX::SFXState_Func::playSFXAtLocation, + DAT_SFXState::ptr)((int)this->units[_currentUnitID].x, + (int)((int)(this->units[_currentUnitID].y)), OpenSHC::DE::SHCDE::FX_CHICKEN_FLAP); + _currentUnitID = DAT_CurrentUnitSlotID::instance; + } + if ((999 < (int)(DAT_GameCore::instance.mapTimeInTicks - this->units[_currentUnitID].time)) + && (_unitType = this->units[_currentUnitID].unitType, + _unitType != OpenSHC::Map::Units::UT_S_TOWER)) { + if (_unitType == OpenSHC::Map::Units::UT_LORD) { + uint uVar12 = (uint)this->units[_currentUnitID].targetY_2; + uVar9 = (uint)this->units[_currentUnitID].targetX_2; + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::setPositionOfUnit, this)( + _currentUnitID, uVar9, uVar12, + (undefined4)((int)((uint) + * (byte*)(DAT_ViewportRenderState::instance.translationMatrix[uVar12] + .addXgetTile + + 0x1d32c38 + uVar9)))); + this->units[DAT_CurrentUnitSlotID::instance].state.generic + = OpenSHC::Map::Units::States::US_IDLEUnk; + this->units[DAT_CurrentUnitSlotID::instance].destinationNeeded + = OpenSHC::Map::Units::Pathfinding::DNE_DESTINATION_HAS_BEEN_SET; + _currentUnitID = DAT_CurrentUnitSlotID::instance; + } else { + this->units[_currentUnitID].state.generic + = OpenSHC::Map::Units::States::US_DISAPPEAR; + this->units[DAT_CurrentUnitSlotID::instance].updateTickTracker = 0; + _currentUnitID = DAT_CurrentUnitSlotID::instance; + } + } + } + UVar6 = this->units[_currentUnitID].unitType; + if (((UVar6 == OpenSHC::Map::Units::UT_S_CATAPULT) + || (UVar6 == OpenSHC::Map::Units::UT_S_FBALLISTA)) + && ((DAT_TileMapState::instance.LogicLayer[this->units[_currentUnitID].tile] & 0x50000000U) + != 0)) { + this->units[_currentUnitID].state.generic = OpenSHC::Map::Units::States::US_DISAPPEAR; + this->units[DAT_CurrentUnitSlotID::instance].updateTickTracker = 0; + _currentUnitID = DAT_CurrentUnitSlotID::instance; + } + } + if ((this->units[_currentUnitID].logicalState == OpenSHC::Map::Units::ULS_NORMAL) + && (((this->units[_currentUnitID].x == 0 || (this->units[_currentUnitID].y == 0)) + || (this->units[_currentUnitID].tile < 0)))) { + this->units[_currentUnitID].state.generic = OpenSHC::Map::Units::States::US_DISAPPEAR; + this->units[DAT_CurrentUnitSlotID::instance].updateTickTracker = 0; + _currentUnitID = DAT_CurrentUnitSlotID::instance; + } + } + DAT_CurrentUnitSlotID::instance = _currentUnitID + 1; + } while ((int)DAT_CurrentUnitSlotID::instance < 2500); + DAT_CurrentUnitSlotID::instance = 1; + if (1 < (int)this->maxUnitCount) { + do { + if (this->units[DAT_CurrentUnitSlotID::instance].logicalState + != OpenSHC::Map::Units::ULS_INVISIBLE) { + if (this->units[DAT_CurrentUnitSlotID::instance].state.generic + == OpenSHC::Map::Units::States::US_MELEE_ATTACK) { + _buildingID = this->units[DAT_CurrentUnitSlotID::instance].attackedUnitID; + psVar4 = &this->units[_buildingID].attackedBy; + *psVar4 = *psVar4 + 1; + if ((int)this->units[_buildingID].attackedUnitID != DAT_CurrentUnitSlotID::instance) { + psVar4 = &this->units[DAT_CurrentUnitSlotID::instance].attackedBy; + *psVar4 = *psVar4 + 1; + } + if ((this->units[_buildingID].attackedBy == 1) + && (this->units[_buildingID].isStalked == 0)) { + DAT_GameCore::instance.cowPoisonTrackerUnk + = DAT_GameCore::instance.cowPoisonTrackerUnk + 1; + } + } + _buildingID = this->units[DAT_CurrentUnitSlotID::instance].movementType_OR_targetUnitID; + if (_buildingID != 0) { + psVar4 = &this->units[_buildingID].huntedBy; + *psVar4 = *psVar4 + 1; + } + _buildingID = this->units[DAT_CurrentUnitSlotID::instance].field266_0x3de; + if (_buildingID != 0) { + psVar4 = &this->units[_buildingID].field265_0x3dc; + *psVar4 = *psVar4 + 1; + } + psVar4 = &this->units[DAT_CurrentUnitSlotID::instance].field97_0xd0; + if (0 < this->units[DAT_CurrentUnitSlotID::instance].field97_0xd0) { + *psVar4 = *psVar4 + -1; + } + } + DAT_CurrentUnitSlotID::instance = DAT_CurrentUnitSlotID::instance + 1; + } while ((int)DAT_CurrentUnitSlotID::instance < (int)this->maxUnitCount); + } + uint _tick0To64 = DAT_GameCore::instance.mapTimeInTicks & 0x3f; + for (int _playerID = 1; _playerID < 9; _playerID = _playerID + 1) { + DAT_GameState::instance.playerDataArray[_playerID].totalTroopsType0 = 0; + DAT_GameState::instance.playerDataArray[_playerID].idlePeasantsCount = 0; + DAT_GameState::instance.playerDataArray[_playerID].totalDefensiveTroopsUnk = 0; + DAT_GameState::instance.playerDataArray[_playerID].totalRaidingTroopsUnk = 0; + DAT_GameState::instance.playerDataArray[_playerID].totalAttackTroops = 0; + DAT_GameState::instance.playerDataArray[_playerID].totalTroopsType6 = 0; + DAT_GameState::instance.playerDataArray[_playerID].totalTroopsType7 = 0; + DAT_GameState::instance.playerDataArray[_playerID].field852_0x2b58 = 0; + DAT_GameState::instance.playerDataArray[_playerID].engineerCountRelated = 0; + DAT_GameState::instance.playerDataArray[_playerID].totalAttackingEngineerTroops = 0; + DAT_GameState::instance.playerDataArray[_playerID].unknownHarrassingSiegeRelated = 0; + DAT_GameState::instance.playerDataArray[_playerID].totalDiggingUnitTroops = 0; + DAT_GameState::instance.playerDataArray[_playerID].totalAssassinTroops = 0; + DAT_GameState::instance.playerDataArray[_playerID].totalUnit2Troops = 0; + DAT_GameState::instance.playerDataArray[_playerID].totalLaddermenTroops = 0; + DAT_GameState::instance.playerDataArray[_playerID].totalTunnelerTroops = 0; + DAT_GameState::instance.playerDataArray[_playerID].totalUnitPatrolTroops = 0; + DAT_GameState::instance.playerDataArray[_playerID].totalUnitBackupTroops = 0; + DAT_GameState::instance.playerDataArray[_playerID].totalUnitEngageTroops = 0; + DAT_GameState::instance.playerDataArray[_playerID].totalUnitSiegeDefTroops = 0; + DAT_GameState::instance.playerDataArray[_playerID].totalMaxDefaultTroops = 0; + DAT_GameState::instance.playerDataArray[_playerID].harassingSiegeEnginesCountUnk = 0; + if (_tick0To64 == 0) { + DAT_GameState::instance.playerDataArray[_playerID].totalTroopValue = 0; + } + } + DAT_CurrentUnitSlotID::instance = 1; + if (1 < (int)this->maxUnitCount) { + do { + if (this->units[DAT_CurrentUnitSlotID::instance].logicalState + != OpenSHC::Map::Units::ULS_INVISIBLE) { + this->unitCount = this->unitCount + 1; + if (this->units[DAT_CurrentUnitSlotID::instance].field64_0x90 != 0) { + MACRO_CALL_MEMBER( + OpenSHC::Map::Units::UnitsState_Func::stampOccupancyFlagOnSurroundingTiles, this)( + DAT_CurrentUnitSlotID::instance); + } + uVar9 = DAT_CurrentUnitSlotID::instance; + DAT_TileMapState::instance.OccupancyLayer[this->units[DAT_CurrentUnitSlotID::instance].tile] + = DAT_TileMapState::instance + .OccupancyLayer[this->units[DAT_CurrentUnitSlotID::instance].tile] + | this->units[DAT_CurrentUnitSlotID::instance].occupancyOrFlag; + if (this->units[uVar9].isSelectable_OR_matchTime != 0) { + _buildingID = this->units[uVar9].owner; + if ((DAT_GameCore::instance.mapTimeInTicks & 0x3f) == 0) { + piVar1 = &DAT_GameState::instance.playerDataArray[_buildingID].totalTroopValue; + _troopValue + = MACRO_CALL_MEMBER(OpenSHC::Map::Units::TroopValueState_Func::getValueOfTroopType, + DAT_TroopValueState::ptr)((UnitType)(short)this->units[uVar9].unitType); + *piVar1 = *piVar1 + _troopValue; + uVar9 = DAT_CurrentUnitSlotID::instance; + if ((char)this->units[DAT_CurrentUnitSlotID::instance].firstNameIndex < '\x01') { + /* + Every 0x3f ticks, assign names to citizen units + */ + + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::assignNameToUnit, this)( + DAT_CurrentUnitSlotID::instance); + uVar9 = DAT_CurrentUnitSlotID::instance; + } + } + UVar6 = this->units[uVar9].unitType; + if (UVar6 == OpenSHC::Map::Units::UT_A_HARCHER) { + DAT_TileMapState::instance.SEC_TileMap1104[this->units[uVar9].tile] = '\x06'; + } else if (UVar6 == OpenSHC::Map::Units::UT_A_FIRETHROWER) { + MACRO_CALL_MEMBER( + OpenSHC::Map::Units::UnitsState_Func::writeSixToTileMap1104InAllDirections, this)( + uVar9, 6); + uVar9 = DAT_CurrentUnitSlotID::instance; + } + UVar6 = this->units[uVar9].unitType; + if (UVar6 != OpenSHC::Map::Units::UT_LORD) { + short sVar7 = this->units[uVar9].aiUnitBehaviourType; + if (sVar7 == 10) { + piVar1 = &DAT_GameState::instance.playerDataArray[_buildingID] + .totalAttackingEngineerTroops; + *piVar1 = *piVar1 + 1; + piVar1 = &DAT_GameState::instance.playerDataArray[_buildingID].totalAttackTroops; + *piVar1 = *piVar1 + 1; + } else if (UVar6 != OpenSHC::Map::Units::UT_E_ENGINEER) { + /* + fixme: TODO, review this bit, cannot be true! + */ + + switch (sVar7) { + case 0: + piVar1 = &DAT_GameState::instance.playerDataArray[_buildingID].totalTroopsType0; + *piVar1 = *piVar1 + 1; + break; + case 1: + case 4: + piVar1 = &DAT_GameState::instance.playerDataArray[_buildingID] + .totalDefensiveTroopsUnk; + *piVar1 = *piVar1 + 1; + break; + case 2: + piVar1 = &DAT_GameState::instance.playerDataArray[_buildingID] + .totalRaidingTroopsUnk; + *piVar1 = *piVar1 + 1; + break; + default: + break; + case 6: + piVar1 = &DAT_GameState::instance.playerDataArray[_buildingID].totalTroopsType6; + *piVar1 = *piVar1 + 1; + break; + case 7: + piVar1 = &DAT_GameState::instance.playerDataArray[_buildingID].totalTroopsType7; + *piVar1 = *piVar1 + 1; + break; + case 0xb: + piVar1 = &DAT_GameState::instance.playerDataArray[_buildingID] + .totalDiggingUnitTroops; + *piVar1 = *piVar1 + 1; + piVar1 + = &DAT_GameState::instance.playerDataArray[_buildingID].totalAttackTroops; + *piVar1 = *piVar1 + 1; + break; + case 0xc: + piVar1 + = &DAT_GameState::instance.playerDataArray[_buildingID].totalAssassinTroops; + *piVar1 = *piVar1 + 1; + piVar1 + = &DAT_GameState::instance.playerDataArray[_buildingID].totalAttackTroops; + *piVar1 = *piVar1 + 1; + break; + case 0xd: + piVar1 = &DAT_GameState::instance.playerDataArray[_buildingID].totalUnit2Troops; + *piVar1 = *piVar1 + 1; + piVar1 + = &DAT_GameState::instance.playerDataArray[_buildingID].totalAttackTroops; + *piVar1 = *piVar1 + 1; + break; + case 0xe: + piVar1 = &DAT_GameState::instance.playerDataArray[_buildingID] + .totalLaddermenTroops; + *piVar1 = *piVar1 + 1; + piVar1 + = &DAT_GameState::instance.playerDataArray[_buildingID].totalAttackTroops; + *piVar1 = *piVar1 + 1; + break; + case 0xf: + piVar1 + = &DAT_GameState::instance.playerDataArray[_buildingID].totalTunnelerTroops; + *piVar1 = *piVar1 + 1; + piVar1 + = &DAT_GameState::instance.playerDataArray[_buildingID].totalAttackTroops; + *piVar1 = *piVar1 + 1; + break; + case 0x10: + piVar1 = &DAT_GameState::instance.playerDataArray[_buildingID] + .totalUnitPatrolTroops; + *piVar1 = *piVar1 + 1; + piVar1 + = &DAT_GameState::instance.playerDataArray[_buildingID].totalAttackTroops; + *piVar1 = *piVar1 + 1; + break; + case 0x11: + piVar1 = &DAT_GameState::instance.playerDataArray[_buildingID] + .totalUnitBackupTroops; + *piVar1 = *piVar1 + 1; + piVar1 + = &DAT_GameState::instance.playerDataArray[_buildingID].totalAttackTroops; + *piVar1 = *piVar1 + 1; + break; + case 0x12: + piVar1 = &DAT_GameState::instance.playerDataArray[_buildingID] + .totalUnitEngageTroops; + *piVar1 = *piVar1 + 1; + piVar1 + = &DAT_GameState::instance.playerDataArray[_buildingID].totalAttackTroops; + *piVar1 = *piVar1 + 1; + break; + case 0x13: + piVar1 = &DAT_GameState::instance.playerDataArray[_buildingID] + .totalUnitSiegeDefTroops; + *piVar1 = *piVar1 + 1; + piVar1 + = &DAT_GameState::instance.playerDataArray[_buildingID].totalAttackTroops; + *piVar1 = *piVar1 + 1; + break; + case 0x14: + piVar1 = &DAT_GameState::instance.playerDataArray[_buildingID] + .totalMaxDefaultTroops; + *piVar1 = *piVar1 + 1; + piVar1 + = &DAT_GameState::instance.playerDataArray[_buildingID].totalAttackTroops; + *piVar1 = *piVar1 + 1; + break; + case 0x15: + piVar1 = &DAT_GameState::instance.playerDataArray[_buildingID] + .harassingSiegeEnginesCountUnk; + *piVar1 = *piVar1 + 1; + } + } + } + } + _buildingID = this->units[uVar9].unitType; + if ((((_buildingID == OpenSHC::Map::Units::UT_E_ARCHER) + || (_buildingID == OpenSHC::Map::Units::UT_A_ARCHER)) + && ((_buildingID = this->units[uVar9].state.generic, + _buildingID == OpenSHC::Map::Units::States::US_AIM_WEAPONUnk + || (_buildingID == OpenSHC::Map::Units::States::US_FIRE_WEAPONUnk)))) + && ((_troopValue = this->units[uVar9].shootTargetedUnit, + 0 < _troopValue && (this->units[_troopValue].uid == this->units[uVar9].targetUID)))) { + this->units[_troopValue].field233_0x39a = 1; + uVar9 = DAT_CurrentUnitSlotID::instance; + } + if ((this->units[uVar9].enemyNoticeFrequencyUnk != 0) + && ((DAT_GameState::instance.mapAndTime.totalGameTicksUnk + & this->units[uVar9].enemyNoticeFrequencyUnk) + == (this->units[uVar9].fixedRng & this->units[uVar9].enemyNoticeFrequencyUnk))) { + if (this->units[uVar9].owner == 0) { + _troopValue = MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func:: + computeDistanceToNearestEnemyForLegacyMissions, + this)(uVar9); + this->units[uVar9].closestEnemyMicroDistance = (short)_troopValue; + uVar9 = DAT_CurrentUnitSlotID::instance; + } else { + dword dVar10 = MACRO_CALL_MEMBER( + OpenSHC::Map::Units::UnitsState_Func::findNearestEnemyAndHeadTowardsIt, this)( + uVar9); + this->units[DAT_CurrentUnitSlotID::instance].closestEnemyMicroDistance = (short)dVar10; + this->units[DAT_CurrentUnitSlotID::instance].assassinsMicroDistanceToEnemyUnk + = this->unitDistanceComputationResultUnk; + uVar9 = DAT_CurrentUnitSlotID::instance; + } + } + psVar4 = &this->units[uVar9].lookForEnemy; + if (this->units[uVar9].lookForEnemy < 0) { + *psVar4 = *psVar4 + 1; + } else { + *psVar4 = 0; + } + psVar4 = &this->units[DAT_CurrentUnitSlotID::instance].unknownMovementRelated_0x2d2; + if (this->units[DAT_CurrentUnitSlotID::instance].unknownMovementRelated_0x2d2 < 0) { + *psVar4 = *psVar4 + 1; + } + this->units[DAT_CurrentUnitSlotID::instance].SA = 0; + if (DAT_TileMapState::instance.refreshRelatedOne != 0) { + bVar13 = this->units[DAT_CurrentUnitSlotID::instance].heightDiv10; + if (bVar13 != 0) { + undefined1* puVar2 = &this->units[DAT_CurrentUnitSlotID::instance].padding_0x83[0]; + *puVar2 = *puVar2 + - *(char*)((int)DAT_UnitPropertiesDefinedData::ptr + + (DAT_UpdateUnitsTracker::instance - (uint)bVar13) * 4 + 0x11a24); + if (100 < (byte)this->units[DAT_CurrentUnitSlotID::instance].padding_0x83[0]) { + this->units[DAT_CurrentUnitSlotID::instance].padding_0x83[0] = 0; + } + if ((int)((byte)this->units[DAT_CurrentUnitSlotID::instance].heightDiv10 + 0xd) + <= DAT_UpdateUnitsTracker::instance) { + this->units[DAT_CurrentUnitSlotID::instance].heightDiv10 = 0; + this->units[DAT_CurrentUnitSlotID::instance].padding_0x83[0] = 0; + } + } + } + } + DAT_CurrentUnitSlotID::instance = DAT_CurrentUnitSlotID::instance + 1; + } while ((int)DAT_CurrentUnitSlotID::instance < (int)this->maxUnitCount); + } + MACRO_CALL_MEMBER(OpenSHC::Map::Entities::EntityState_Func::recountActiveFires, DAT_EntityState::ptr)(); + MACRO_CALL_MEMBER( + OpenSHC::Map::Entities::EntityState_Func::flagUnitsWithActiveEntity, DAT_EntityState::ptr)(); + DAT_CurrentUnitSlotID::instance = 1; + if (1 < (int)this->maxUnitCount) { + do { + switch (this->units[DAT_CurrentUnitSlotID::instance].logicalState) { + case OpenSHC::Map::Units::ULS_INVISIBLE: + break; + case OpenSHC::Map::Units::ULS_REMOVE: + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::deleteUnit, this)( + DAT_CurrentUnitSlotID::instance); + break; + case ((UnitLogicState)5): + this->units[DAT_CurrentUnitSlotID::instance].logicalState = ((UnitLogicState)1); + break; + default: + if (this->units[DAT_CurrentUnitSlotID::instance].logicalState + == OpenSHC::Map::Units::ULS_TRANSITIONING) { + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::changeUnitType, this)( + DAT_CurrentUnitSlotID::instance); + } else if (this->units[DAT_CurrentUnitSlotID::instance].logicalState == ((UnitLogicState)1)) { + this->units[DAT_CurrentUnitSlotID::instance].logicalState = OpenSHC::Map::Units::ULS_NORMAL; + } + int* _ptr_animationTicker = &this->units[DAT_CurrentUnitSlotID::instance].animationTicker; + *_ptr_animationTicker = *_ptr_animationTicker + 1; + int _animationTicker = this->units[DAT_CurrentUnitSlotID::instance].animationTicker; + if (this->units[DAT_CurrentUnitSlotID::instance].animationSpeed + + this->units[DAT_CurrentUnitSlotID::instance].animationLeapTicksTotal + < _animationTicker) { + this->units[DAT_CurrentUnitSlotID::instance].animationLeapTicksTotal = _animationTicker; + piVar1 = &this->units[DAT_CurrentUnitSlotID::instance].animationCycleNumber; + *piVar1 = *piVar1 + 1; + this->units[DAT_CurrentUnitSlotID::instance].animationCycleNumberHasJustIncremented = TRUE; + uVar9 = DAT_CurrentUnitSlotID::instance; + if (999 < this->units[DAT_CurrentUnitSlotID::instance].animationCycleNumber) { + this->units[DAT_CurrentUnitSlotID::instance].animationCycleNumber = 0; + } + } else { + this->units[DAT_CurrentUnitSlotID::instance].animationCycleNumberHasJustIncremented = FALSE; + uVar9 = DAT_CurrentUnitSlotID::instance; + } + _buildingID = (short)DAT_TileMapState::instance.mapOrientation; + if (this->units[uVar9].field39_0x58 == 0) { + if (this->units[uVar9].state.generic != OpenSHC::Map::Units::States::US_MELEE_ATTACK) { + this->units[uVar9].facingDirectionMapOrientationCorrected + = this->units[uVar9].facingDirection - _buildingID; + } else { + this->units[uVar9].facingDirectionMapOrientationCorrected + = this->units[uVar9].orientation - _buildingID; + } + } else { + this->units[uVar9].facingDirectionMapOrientationCorrected + = (short)DAT_TileMapState::instance.field84_0x5548a4 - _buildingID; + } + psVar4 = &this->units[DAT_CurrentUnitSlotID::instance].facingDirectionMapOrientationCorrected; + if (this->units[DAT_CurrentUnitSlotID::instance].facingDirectionMapOrientationCorrected < 0) { + *psVar4 = *psVar4 + 8; + } + uVar9 = DAT_CurrentUnitSlotID::instance; + _buildingID = this->units[DAT_CurrentUnitSlotID::instance].owner; + piVar1 = &DAT_GameState::instance.playerDataArray[_buildingID].countEntities; + *piVar1 = *piVar1 + 1; + if (DAT_UnitPropertiesDefinedData::instance.COMPUTER_MANAGED[(short)this->units[uVar9].unitType] + != 0) { + piVar1 = &DAT_GameState::instance.playerDataArray[_buildingID].currentPopulation_2; + *piVar1 = *piVar1 + 1; + } + DAT_UnitHasBecomeIdle::instance = 0; + if (((((this->units[uVar9].dying != 0) + && (this->units[uVar9].state.generic != OpenSHC::Map::Units::States::US_DISAPPEAR)) + && (UVar6 = this->units[uVar9].unitType, UVar6 != OpenSHC::Map::Units::UT_BURNINGMAN)) + && ((UVar6 != OpenSHC::Map::Units::UT_BURNING_ANIMAL_BIG + && (UVar6 != OpenSHC::Map::Units::UT_BURNING_ANIMAL_SMALL)))) + && (((short)this->units[uVar9].state.generic < 0x6f + || (0x75 < (short)this->units[uVar9].state.generic)))) { + this->units[uVar9].state.generic = OpenSHC::Map::Units::States::US_DEATH_01; + this->units[DAT_CurrentUnitSlotID::instance].animationCycleNumber = 0; + uVar9 = DAT_CurrentUnitSlotID::instance; + } + if (DAT_UnitPropertiesDefinedData::instance + .COMPUTER_CONTROLLED[(short)this->units[uVar9].unitType] + != 0) { + _buildingID = this->units[uVar9].workplaceBuildingID_1; + if (DAT_BuildingsState::instance.buildings[_buildingID].uid + == this->units[uVar9].workplaceBuildingUID) { + if (DAT_BuildingsState::instance.buildings[_buildingID].sleeping != false) { + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func:: + makeUnitStopWalkingByClearingPathProgressState, + this)(uVar9); + if (7 < this->units[DAT_CurrentUnitSlotID::instance].movementRelated) { + this->units[DAT_CurrentUnitSlotID::instance].logicalState + = OpenSHC::Map::Units::ULS_TRANSITIONING; + this->units[DAT_CurrentUnitSlotID::instance].unitTypeToChangeInto + = OpenSHC::Map::Units::UT_PEASANT; + this->units[DAT_CurrentUnitSlotID::instance].state_2 = 0; + this->units[DAT_CurrentUnitSlotID::instance].workplaceBuildingID_1 = 0; + MACRO_CALL_MEMBER( + OpenSHC::Map::Units::UnitsState_Func::clearHiddenFlagAndUpdatePosition, + this)(DAT_CurrentUnitSlotID::instance); + } + this->units[DAT_CurrentUnitSlotID::instance].disappearFadeAlphaCountdown = 0; + uVar9 = DAT_CurrentUnitSlotID::instance; + } + } else { + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func:: + makeUnitStopWalkingByClearingPathProgressState, + this)(uVar9); + uVar9 = DAT_CurrentUnitSlotID::instance; + if (7 < this->units[DAT_CurrentUnitSlotID::instance].movementRelated) { + this->units[DAT_CurrentUnitSlotID::instance].logicalState + = OpenSHC::Map::Units::ULS_TRANSITIONING; + this->units[DAT_CurrentUnitSlotID::instance].unitTypeToChangeInto + = OpenSHC::Map::Units::UT_PEASANT; + this->units[DAT_CurrentUnitSlotID::instance].state_2 = 0; + this->units[DAT_CurrentUnitSlotID::instance].workplaceBuildingID_1 = 0; + MACRO_CALL_MEMBER( + OpenSHC::Map::Units::UnitsState_Func::clearHiddenFlagAndUpdatePosition, this)( + DAT_CurrentUnitSlotID::instance); + uVar9 = DAT_CurrentUnitSlotID::instance; + } + } + } + this->units[uVar9].field131_0x2ac = 0; + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::processMeleeInitiation, this)( + DAT_CurrentUnitSlotID::instance); + this->units[DAT_CurrentUnitSlotID::instance].field143_0x2c4 + = this->units[DAT_CurrentUnitSlotID::instance].state.generic; + if (this->units[DAT_CurrentUnitSlotID::instance].logicalState + != OpenSHC::Map::Units::ULS_TRANSITIONING) { + /* + Update unit state + */ + + (*DAT_UnitPropertiesDefinedData::instance.UpdateUnitFunctions + [(short)this->units[DAT_CurrentUnitSlotID::instance].unitType])(); + } + uVar9 = DAT_CurrentUnitSlotID::instance; + UnitStateShort UVar8 = this->units[DAT_CurrentUnitSlotID::instance].field143_0x2c4; + if (((UVar8 != this->units[DAT_CurrentUnitSlotID::instance].state.generic) + && ((UVar8 + == (OpenSHC::Map::Units::States::US_DEATH_02 + | OpenSHC::Map::Units::States::US_STAND_UPUnk + | OpenSHC::Map::Units::States::US_RELOAD_WEAPONUnk) + || (UVar8 == OpenSHC::Map::Units::States::US_DIG)))) + && (_troopValue = this->units[DAT_CurrentUnitSlotID::instance].digTileTarget, + DAT_TileMapState::instance.moats[_troopValue].owner != '\0')) { + char* pcVar3 = &DAT_TileMapState::instance.moats[_troopValue].someCountDown; + *pcVar3 = *pcVar3 + -0x14; + } + this->units[uVar9].field41_0x5c = 0; + if (this->units[DAT_CurrentUnitSlotID::instance].usingTeleport == 0) { + piVar1 = &this->units[DAT_CurrentUnitSlotID::instance].field200_0x354; + /* + Not climbing + */ + + *piVar1 = *piVar1 + 1; + _troopValue = this->units[DAT_CurrentUnitSlotID::instance].field200_0x354; + if ((int)this->units[DAT_CurrentUnitSlotID::instance].calculatedMovementSpeed + + (int)this->units[DAT_CurrentUnitSlotID::instance].stateBasedSpeed + + (int)this->units[DAT_CurrentUnitSlotID::instance].moveDelay + < _troopValue - this->units[DAT_CurrentUnitSlotID::instance].field199_0x350) { + this->units[DAT_CurrentUnitSlotID::instance].field199_0x350 = _troopValue; + psVar4 = &this->units[DAT_CurrentUnitSlotID::instance].movementRunUpTime; + if (this->units[DAT_CurrentUnitSlotID::instance].movementRunUpTime < 1) { + *psVar4 = 0; + } else { + *psVar4 = *psVar4 + -1; + } + _troopValue = MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::processUnitMove, + this)(DAT_CurrentUnitSlotID::instance, + (int)((int)(this->units[DAT_CurrentUnitSlotID::instance].stateBasedSpeed))); + if (_troopValue != 0) { + if (((this->units[DAT_CurrentUnitSlotID::instance].state.generic + == OpenSHC::Map::Units::States::US_MOVE_TO_DESTINATION) + && (this->units[DAT_CurrentUnitSlotID::instance].disappearFadeAlphaCountdown + != 0)) + && (this->units[DAT_CurrentUnitSlotID::instance].fadeType == 0)) { + this->units[DAT_CurrentUnitSlotID::instance].disappearFadeAlphaCountdown = 0; + } + psVar4 = &this->units[DAT_CurrentUnitSlotID::instance].field218_0x37e; + *psVar4 = *psVar4 + 1; + if (0xf < this->units[DAT_CurrentUnitSlotID::instance].field218_0x37e) { + this->units[DAT_CurrentUnitSlotID::instance].field218_0x37e = 0; + } + psVar4 = &this->units[DAT_CurrentUnitSlotID::instance].field217_0x37c; + *psVar4 = *psVar4 + 2; + if (0xd < this->units[DAT_CurrentUnitSlotID::instance].field217_0x37c) { + this->units[DAT_CurrentUnitSlotID::instance].field217_0x37c = 0; + } + psVar4 = &this->units[DAT_CurrentUnitSlotID::instance].field215_0x378; + *psVar4 = *psVar4 + 2; + if (0xf < this->units[DAT_CurrentUnitSlotID::instance].field215_0x378) { + this->units[DAT_CurrentUnitSlotID::instance].field215_0x378 = 0; + } + psVar4 = &this->units[DAT_CurrentUnitSlotID::instance].field254_0x3c6; + *psVar4 = *psVar4 + 1; + if (0x11 < this->units[DAT_CurrentUnitSlotID::instance].field254_0x3c6) { + this->units[DAT_CurrentUnitSlotID::instance].field254_0x3c6 = 0; + } + psVar4 = &this->units[DAT_CurrentUnitSlotID::instance].field312_0x428; + *psVar4 = *psVar4 + 1; + if (0x17 < this->units[DAT_CurrentUnitSlotID::instance].field312_0x428) { + this->units[DAT_CurrentUnitSlotID::instance].field312_0x428 = 0; + } + } + psVar4 = &this->units[DAT_CurrentUnitSlotID::instance].field216_0x37a; + *psVar4 = *psVar4 + 1; + if (0xb < this->units[DAT_CurrentUnitSlotID::instance].field216_0x37a) { + this->units[DAT_CurrentUnitSlotID::instance].field216_0x37a = 0; + } + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::calculateUnitMovementSpeed, + this)(DAT_CurrentUnitSlotID::instance); + } + } else { + /* + Climbing + */ + + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::unitClimbing, this)( + DAT_CurrentUnitSlotID::instance); + } + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::recomputeUnitStandingHeight, this)( + DAT_CurrentUnitSlotID::instance); + switch (this->units[DAT_CurrentUnitSlotID::instance].field_0x30_animRelated) { + case 8: + this->units[DAT_CurrentUnitSlotID::instance].gfxNumber + = (int)this->units[DAT_CurrentUnitSlotID::instance] + .facingDirectionMapOrientationCorrected + + this->units[DAT_CurrentUnitSlotID::instance].animationSheetFrameOffset; + piVar1 = &this->units[DAT_CurrentUnitSlotID::instance].gfxNumber; + *piVar1 = *piVar1 + this->units[DAT_CurrentUnitSlotID::instance].field215_0x378 * 8; + if (((this->units[DAT_CurrentUnitSlotID::instance].unitType + == OpenSHC::Map::Units::UT_A_HARCHER) + && (_buildingID + = this->units[DAT_CurrentUnitSlotID::instance].horseArcherShootingVariation, + _buildingID != 4)) + && ((_buildingID != 5 && (_buildingID != 6)))) { + this->units[DAT_CurrentUnitSlotID::instance].imageIDUnk + = this->units[DAT_CurrentUnitSlotID::instance].gfxNumber; + } + break; + case 9: + this->units[DAT_CurrentUnitSlotID::instance].gfxNumber + = (int)this->units[DAT_CurrentUnitSlotID::instance] + .facingDirectionMapOrientationCorrected + + this->units[DAT_CurrentUnitSlotID::instance].animationSheetFrameOffset; + piVar1 = &this->units[DAT_CurrentUnitSlotID::instance].gfxNumber; + *piVar1 = *piVar1 + (this->units[DAT_CurrentUnitSlotID::instance].field215_0x378 * 8) / 2; + break; + case 0xc: + this->units[DAT_CurrentUnitSlotID::instance].gfxNumber + = (int)this->units[DAT_CurrentUnitSlotID::instance] + .facingDirectionMapOrientationCorrected + + this->units[DAT_CurrentUnitSlotID::instance].animationSheetFrameOffset; + piVar1 = &this->units[DAT_CurrentUnitSlotID::instance].gfxNumber; + *piVar1 = *piVar1 + this->units[DAT_CurrentUnitSlotID::instance].field216_0x37a * 8; + break; + case 0xe: + this->units[DAT_CurrentUnitSlotID::instance].gfxNumber + = (int)this->units[DAT_CurrentUnitSlotID::instance] + .facingDirectionMapOrientationCorrected + + this->units[DAT_CurrentUnitSlotID::instance].animationSheetFrameOffset; + piVar1 = &this->units[DAT_CurrentUnitSlotID::instance].gfxNumber; + *piVar1 = *piVar1 + this->units[DAT_CurrentUnitSlotID::instance].field217_0x37c * 8; + break; + case 0x10: + this->units[DAT_CurrentUnitSlotID::instance].gfxNumber + = (int)this->units[DAT_CurrentUnitSlotID::instance] + .facingDirectionMapOrientationCorrected + + this->units[DAT_CurrentUnitSlotID::instance].animationSheetFrameOffset; + piVar1 = &this->units[DAT_CurrentUnitSlotID::instance].gfxNumber; + *piVar1 = *piVar1 + this->units[DAT_CurrentUnitSlotID::instance].field218_0x37e * 8; + if (this->units[DAT_CurrentUnitSlotID::instance].unitType + == OpenSHC::Map::Units::UT_A_HARCHER) { + this->units[DAT_CurrentUnitSlotID::instance].imageIDUnk + = this->units[DAT_CurrentUnitSlotID::instance].gfxNumber; + } + if (this->units[DAT_CurrentUnitSlotID::instance].unitType + == OpenSHC::Map::Units::UT_E_KNIGHT) { + this->units[DAT_CurrentUnitSlotID::instance].imageIDUnk + = this->units[DAT_CurrentUnitSlotID::instance].gfxNumber; + if ((DAT_CurrentUnitSlotID::instance & 1) == 0) { + if (((this->units[DAT_CurrentUnitSlotID::instance].stateBasedSpeed != 0) + && ((this->units[DAT_CurrentUnitSlotID::instance] + .movementType_OR_targetUnitID + != 0 + || (this->units[DAT_CurrentUnitSlotID::instance].targetingType + == OpenSHC::Map::Units::UIT_UNIT_ATTACK_UNIT)))) + && (this->units[DAT_CurrentUnitSlotID::instance].totalSizeOfPathPlan + -0x10 + <= (int)this->units[DAT_CurrentUnitSlotID::instance] + .currentIndexInPathPlan)) { + piVar1 = &this->units[DAT_CurrentUnitSlotID::instance].imageIDUnk; + *piVar1 = *piVar1 + 0x80; + } + } else { + piVar1 = &this->units[DAT_CurrentUnitSlotID::instance].imageIDUnk; + *piVar1 = *piVar1 + 0x270; + } + } + break; + case 0x11: + this->units[DAT_CurrentUnitSlotID::instance].gfxNumber + = this->units[DAT_CurrentUnitSlotID::instance].facingDirectionMapOrientationCorrected + * 0x10 + + this->units[DAT_CurrentUnitSlotID::instance].animationSheetFrameOffset; + piVar1 = &this->units[DAT_CurrentUnitSlotID::instance].gfxNumber; + *piVar1 = *piVar1 + (int)this->units[DAT_CurrentUnitSlotID::instance].field218_0x37e; + break; + case 0x12: + this->units[DAT_CurrentUnitSlotID::instance].gfxNumber + = (int)this->units[DAT_CurrentUnitSlotID::instance] + .facingDirectionMapOrientationCorrected + + this->units[DAT_CurrentUnitSlotID::instance].animationSheetFrameOffset; + piVar1 = &this->units[DAT_CurrentUnitSlotID::instance].gfxNumber; + *piVar1 = *piVar1 + this->units[DAT_CurrentUnitSlotID::instance].field254_0x3c6 * 8; + break; + case 0x13: + case 0x14: + this->units[DAT_CurrentUnitSlotID::instance].imageIDUnk + = (int)this->units[DAT_CurrentUnitSlotID::instance] + .facingDirectionMapOrientationCorrected + + this->units[DAT_CurrentUnitSlotID::instance].animationSheetFrameOffset; + piVar1 = &this->units[DAT_CurrentUnitSlotID::instance].imageIDUnk; + *piVar1 + = *piVar1 + ((int)this->units[DAT_CurrentUnitSlotID::instance].field215_0x378 / 2) * 8; + break; + case 0x15: + this->units[DAT_CurrentUnitSlotID::instance].gfxNumber + = (int)this->units[DAT_CurrentUnitSlotID::instance] + .facingDirectionMapOrientationCorrected + + this->units[DAT_CurrentUnitSlotID::instance].animationSheetFrameOffset; + piVar1 = &this->units[DAT_CurrentUnitSlotID::instance].gfxNumber; + *piVar1 = *piVar1 + this->units[DAT_CurrentUnitSlotID::instance].field218_0x37e * 8; + _troopValue + = this->units[DAT_CurrentUnitSlotID::instance].facingDirectionMapOrientationCorrected + + 0x80 + this->units[DAT_CurrentUnitSlotID::instance].animationSheetFrameOffset; + this->units[DAT_CurrentUnitSlotID::instance].imageIDUnk = _troopValue; + piVar1 = &this->units[DAT_CurrentUnitSlotID::instance].imageIDUnk; + *piVar1 = *piVar1 + this->units[DAT_CurrentUnitSlotID::instance].field218_0x37e * 8; + break; + case 0x16: + uVar9 = (int)this->units[DAT_CurrentUnitSlotID::instance] + .facingDirectionMapOrientationCorrected + + 4U + & 0x80000007; + if ((int)uVar9 < 0) { + uVar9 = (uVar9 - 1 | 0xfffffff8) + 1; + } + this->units[DAT_CurrentUnitSlotID::instance].gfxNumber = uVar9 + 0x151; + piVar1 = &this->units[DAT_CurrentUnitSlotID::instance].gfxNumber; + *piVar1 + = *piVar1 + ((byte)this->units[DAT_CurrentUnitSlotID::instance].field218_0x37e & 3) * 8; + uVar9 = (int)this->units[DAT_CurrentUnitSlotID::instance] + .facingDirectionMapOrientationCorrected + + 4U + & 0x80000007; + if ((int)uVar9 < 0) { + uVar9 = (uVar9 - 1 | 0xfffffff8) + 1; + } + _troopValue = uVar9 + 0x1d1; + this->units[DAT_CurrentUnitSlotID::instance].imageIDUnk = _troopValue; + piVar1 = &this->units[DAT_CurrentUnitSlotID::instance].imageIDUnk; + *piVar1 = *piVar1 + this->units[DAT_CurrentUnitSlotID::instance].field218_0x37e * 8; + break; + case 0x18: + this->units[DAT_CurrentUnitSlotID::instance].gfxNumber + = (int)this->units[DAT_CurrentUnitSlotID::instance] + .facingDirectionMapOrientationCorrected + + this->units[DAT_CurrentUnitSlotID::instance].animationSheetFrameOffset; + piVar1 = &this->units[DAT_CurrentUnitSlotID::instance].gfxNumber; + *piVar1 = *piVar1 + this->units[DAT_CurrentUnitSlotID::instance].field312_0x428 * 8; + break; + case 99: + this->units[DAT_CurrentUnitSlotID::instance].imageID2 + = (int)this->units[DAT_CurrentUnitSlotID::instance] + .facingDirectionMapOrientationCorrected + + this->units[DAT_CurrentUnitSlotID::instance].animationSheetFrameOffset; + piVar1 = &this->units[DAT_CurrentUnitSlotID::instance].imageID2; + *piVar1 + = *piVar1 + ((int)this->units[DAT_CurrentUnitSlotID::instance].field215_0x378 / 2) * 8; + } + psVar4 = &this->units[DAT_CurrentUnitSlotID::instance].unitSpeedMatchingRelatedUnk; + if (this->units[DAT_CurrentUnitSlotID::instance].unitSpeedMatchingRelatedUnk != 0) { + *psVar4 = *psVar4 + -1; + } + bVar13 = this->units[DAT_CurrentUnitSlotID::instance].fadeType; + if (bVar13 != 0) { + if (bVar13 == 1) { + this->units[DAT_CurrentUnitSlotID::instance].disappearFadeAlphaCountdown + = (byte)DAT_UnitPropertiesDefinedData::instance.FadeAlpha_Values_1_2 + [(char)this->units[DAT_CurrentUnitSlotID::instance].fadeCounter]; + } else { + if (bVar13 == 2) { + bVar13 = (byte)DAT_UnitPropertiesDefinedData::instance.FadeAlpha_Values_1_2 + [(char)this->units[DAT_CurrentUnitSlotID::instance].fadeCounter]; + } else { + byte bVar5 = this->units[DAT_CurrentUnitSlotID::instance].fadeCounter; + if (bVar13 == 3) { + bVar13 = (byte)DAT_UnitPropertiesDefinedData::instance + .FadeAlpha_Values_3[(char)bVar5]; + } else { + bVar13 = (byte)DAT_UnitPropertiesDefinedData::instance + .FadeAlpha_Values_4[(char)bVar5]; + } + } + this->units[DAT_CurrentUnitSlotID::instance].disappearFadeAlphaCountdown = bVar13; + } + byte* pbVar11 = &this->units[DAT_CurrentUnitSlotID::instance].fadeCounter; + *pbVar11 = *pbVar11 + 1; + if ((char)this->units[DAT_CurrentUnitSlotID::instance].disappearFadeAlphaCountdown + < '\x01') { + this->units[DAT_CurrentUnitSlotID::instance].fadeType = 0; + this->units[DAT_CurrentUnitSlotID::instance].fadeCounter = 0; + } + } + } + DAT_CurrentUnitSlotID::instance = DAT_CurrentUnitSlotID::instance + 1; + } while ((int)DAT_CurrentUnitSlotID::instance < (int)this->maxUnitCount); + } + if (DAT_TileMapState::instance.refreshRelatedOne == 0) { + DAT_UpdateUnitsTracker::instance = 0; + return; + } + DAT_UpdateUnitsTracker::instance = DAT_UpdateUnitsTracker::instance + 1; + return; + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index bee03eb15..a9433c6e0 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -66991,7 +66991,7 @@ SHC_3BB0A8C1_0x005792F8 | 0.0% | Pending SHC_3BB0A8C1_0x005792FC | 0.0% | Pending -SHC_3BB0A8C1_0x00579300 | 0.0% | Pending +SHC_3BB0A8C1_0x00579300 | 28.5% | reg alloc, dup tails SHC_3BB0A8C1_0x00579380 | 0.0% | Pending From dd6c69056c476a8ce197aa162f8f383010c822bf Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 10:55:01 +0200 Subject: [PATCH 195/299] reimplement: SHC_3BB0A8C1_0x00536C90 100.00% Reimplemented --- .../Units/UnitsState/queueUnitTypeCommand.cpp | 24 +++++++++++++++++++ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 src/OpenSHC/Map/Units/UnitsState/queueUnitTypeCommand.cpp diff --git a/src/OpenSHC/Map/Units/UnitsState/queueUnitTypeCommand.cpp b/src/OpenSHC/Map/Units/UnitsState/queueUnitTypeCommand.cpp new file mode 100644 index 000000000..10ebcff56 --- /dev/null +++ b/src/OpenSHC/Map/Units/UnitsState/queueUnitTypeCommand.cpp @@ -0,0 +1,24 @@ +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Synchrony/GameSynchronyState.func.hpp" +#include "OpenSHC/Commands/GameCommandType.hpp" + +#include "OpenSHC/Globals/DAT_GameSynchronyState.hpp" + +namespace OpenSHC { +namespace Map { + namespace Units { + + using OpenSHC::Commands::GameCommandType; + + // FUNCTION: STRONGHOLDCRUSADER 0x00536C90 + void UnitsState::queueUnitTypeCommand(undefined4 unitType) + { + DAT_GameSynchronyState::instance.DAT_GameCommandParam0 = 0xffffffff; + DAT_GameSynchronyState::instance.DAT_GameCommandParam1 = unitType; + MACRO_CALL_MEMBER(OpenSHC::Synchrony::GameSynchronyState_Func::queueCommand, DAT_GameSynchronyState::ptr)( + OpenSHC::Commands::GCT_ESCAPE); + } + + } +} +} diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index a9433c6e0..3695b61ac 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -51205,7 +51205,7 @@ SHC_3BB0A8C1_0x00536A60 | 87.3% | array init loop differs SHC_3BB0A8C1_0x00536C70 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x00536C90 | 0.0% | Pending +SHC_3BB0A8C1_0x00536C90 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00536CC0 | 100.0% | Reimplemented From 8bff1887e17248a3832b0d73d02fe6b43b08d013 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 15:25:43 +0200 Subject: [PATCH 196/299] reimplement: SHC_3BB0A8C1_0x00549C70 29.18% mask reg alloc, frame ptr --- .../UnitsState/processMeleeInitiation.cpp | 70 +++++++------------ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 27 insertions(+), 45 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/processMeleeInitiation.cpp b/src/OpenSHC/Map/Units/UnitsState/processMeleeInitiation.cpp index c32e67510..998361023 100644 --- a/src/OpenSHC/Map/Units/UnitsState/processMeleeInitiation.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/processMeleeInitiation.cpp @@ -75,55 +75,49 @@ namespace Map { _hasEnemyOnOwnTile = 0; _teamBitFlags = MACRO_CALL_MEMBER( OpenSHC::Game::GameStateStructures_Func::teamToBitFlagsUnk, DAT_GameState::ptr)(unitID); - DAT_TileMapState::instance.field213_0x554a48 = 0; + uint _enemyNeighbourFlags = 0; if ((*(uint*)((uchar*)DAT_TileMapState::instance.ptr_OccupancyLayer + DAT_TileMapState::instance.DAT_SomeTile + 1) & _teamBitFlags) != 0) { - DAT_TileMapState::instance.field213_0x554a48 = 0x20; + _enemyNeighbourFlags = 0x20; } if ((*(uint*)((uchar*)DAT_TileMapState::instance.ptr_OccupancyLayer + DAT_TileMapState::instance.DAT_SomeTile + -1) & _teamBitFlags) != 0) { - DAT_TileMapState::instance.field213_0x554a48 = DAT_TileMapState::instance.field213_0x554a48 | 2; + _enemyNeighbourFlags = _enemyNeighbourFlags | 2; } if ((*(uint*)((uchar*)DAT_TileMapState::instance.ptr_OccupancyLayer + DAT_TileMapState::instance.DAT_SomeTile + 2) & _teamBitFlags) != 0) { - DAT_TileMapState::instance.field213_0x554a48 - = DAT_TileMapState::instance.field213_0x554a48 | 0x80000; + _enemyNeighbourFlags = _enemyNeighbourFlags | 0x80000; } if ((*(uint*)((uchar*)DAT_TileMapState::instance.ptr_OccupancyLayer + DAT_TileMapState::instance.DAT_SomeTile + -2) & _teamBitFlags) != 0) { - DAT_TileMapState::instance.field213_0x554a48 - = DAT_TileMapState::instance.field213_0x554a48 | 0x800; + _enemyNeighbourFlags = _enemyNeighbourFlags | 0x800; } _occupancyRow = (uint*)((uchar*)DAT_TileMapState::instance.ptr_OccupancyLayer + *(int*)((uchar*)DAT_TileMapState::instance.ptr_MovementDirectionTranslationMatrix + DAT_TileMapState::instance.DAT_SomeY * 0x20) + DAT_TileMapState::instance.DAT_SomeTile); if ((*(uint*)((int)_occupancyRow + -1) & _teamBitFlags) != 0) { - DAT_TileMapState::instance.field213_0x554a48 = DAT_TileMapState::instance.field213_0x554a48 | 1; + _enemyNeighbourFlags = _enemyNeighbourFlags | 1; } if ((*(uint*)((int)_occupancyRow + 1) & _teamBitFlags) != 0) { - DAT_TileMapState::instance.field213_0x554a48 - = DAT_TileMapState::instance.field213_0x554a48 | 0x40; + _enemyNeighbourFlags = _enemyNeighbourFlags | 0x40; } if ((*_occupancyRow & _teamBitFlags) != 0) { - DAT_TileMapState::instance.field213_0x554a48 - = DAT_TileMapState::instance.field213_0x554a48 | 0x80; + _enemyNeighbourFlags = _enemyNeighbourFlags | 0x80; } if ((*(uint*)((int)_occupancyRow + -2) & _teamBitFlags) != 0) { - DAT_TileMapState::instance.field213_0x554a48 - = DAT_TileMapState::instance.field213_0x554a48 | 0x400; + _enemyNeighbourFlags = _enemyNeighbourFlags | 0x400; } if ((*(uint*)((int)_occupancyRow + 2) & _teamBitFlags) != 0) { - DAT_TileMapState::instance.field213_0x554a48 - = DAT_TileMapState::instance.field213_0x554a48 | 0x100000; + _enemyNeighbourFlags = _enemyNeighbourFlags | 0x100000; } _occupancyRow = (uint*)((uchar*)DAT_TileMapState::instance.ptr_OccupancyLayer + *(int*)((int)((uchar*)DAT_TileMapState::instance.ptr_MovementDirectionTranslationMatrix @@ -131,22 +125,19 @@ namespace Map { + 0x10) + DAT_TileMapState::instance.DAT_SomeTile); if ((*(uint*)((int)_occupancyRow + -1) & _teamBitFlags) != 0) { - DAT_TileMapState::instance.field213_0x554a48 = DAT_TileMapState::instance.field213_0x554a48 | 4; + _enemyNeighbourFlags = _enemyNeighbourFlags | 4; } if ((*(uint*)((int)_occupancyRow + 1) & _teamBitFlags) != 0) { - DAT_TileMapState::instance.field213_0x554a48 - = DAT_TileMapState::instance.field213_0x554a48 | 0x10; + _enemyNeighbourFlags = _enemyNeighbourFlags | 0x10; } if ((*_occupancyRow & _teamBitFlags) != 0) { - DAT_TileMapState::instance.field213_0x554a48 = DAT_TileMapState::instance.field213_0x554a48 | 8; + _enemyNeighbourFlags = _enemyNeighbourFlags | 8; } if ((*(uint*)((int)_occupancyRow + -2) & _teamBitFlags) != 0) { - DAT_TileMapState::instance.field213_0x554a48 - = DAT_TileMapState::instance.field213_0x554a48 | 0x1000; + _enemyNeighbourFlags = _enemyNeighbourFlags | 0x1000; } if ((*(uint*)((int)_occupancyRow + 2) & _teamBitFlags) != 0) { - DAT_TileMapState::instance.field213_0x554a48 - = DAT_TileMapState::instance.field213_0x554a48 | 0x40000; + _enemyNeighbourFlags = _enemyNeighbourFlags | 0x40000; } _occupancyRow = (uint*)((uchar*)DAT_TileMapState::instance.ptr_OccupancyLayer + *(int*)((uchar*)DAT_TileMapState::instance.ptr_MovementDirectionTranslationMatrix @@ -155,24 +146,19 @@ namespace Map { + DAT_TileMapState::instance.DAT_SomeY * 0x20) + DAT_TileMapState::instance.DAT_SomeTile); if ((*(uint*)((int)_occupancyRow + -1) & _teamBitFlags) != 0) { - DAT_TileMapState::instance.field213_0x554a48 - = DAT_TileMapState::instance.field213_0x554a48 | 0x100; + _enemyNeighbourFlags = _enemyNeighbourFlags | 0x100; } if ((*(uint*)((int)_occupancyRow + 1) & _teamBitFlags) != 0) { - DAT_TileMapState::instance.field213_0x554a48 - = DAT_TileMapState::instance.field213_0x554a48 | 0x400000; + _enemyNeighbourFlags = _enemyNeighbourFlags | 0x400000; } if ((*_occupancyRow & _teamBitFlags) != 0) { - DAT_TileMapState::instance.field213_0x554a48 - = DAT_TileMapState::instance.field213_0x554a48 | 0x800000; + _enemyNeighbourFlags = _enemyNeighbourFlags | 0x800000; } if ((*(uint*)((int)_occupancyRow + -2) & _teamBitFlags) != 0) { - DAT_TileMapState::instance.field213_0x554a48 - = DAT_TileMapState::instance.field213_0x554a48 | 0x200; + _enemyNeighbourFlags = _enemyNeighbourFlags | 0x200; } if ((*(uint*)((int)_occupancyRow + 2) & _teamBitFlags) != 0) { - DAT_TileMapState::instance.field213_0x554a48 - = DAT_TileMapState::instance.field213_0x554a48 | 0x200000; + _enemyNeighbourFlags = _enemyNeighbourFlags | 0x200000; } _occupancyRow = (uint*)((uchar*)DAT_TileMapState::instance.ptr_OccupancyLayer + *(int*)((uchar*)DAT_TileMapState::instance.ptr_MovementDirectionTranslationMatrix @@ -181,25 +167,21 @@ namespace Map { + DAT_TileMapState::instance.DAT_SomeY * 0x20 + 0x10) + DAT_TileMapState::instance.DAT_SomeTile); if ((*(uint*)((int)_occupancyRow + -1) & _teamBitFlags) != 0) { - DAT_TileMapState::instance.field213_0x554a48 - = DAT_TileMapState::instance.field213_0x554a48 | 0x4000; + _enemyNeighbourFlags = _enemyNeighbourFlags | 0x4000; } if ((*(uint*)((int)_occupancyRow + 1) & _teamBitFlags) != 0) { - DAT_TileMapState::instance.field213_0x554a48 - = DAT_TileMapState::instance.field213_0x554a48 | 0x10000; + _enemyNeighbourFlags = _enemyNeighbourFlags | 0x10000; } if ((*_occupancyRow & _teamBitFlags) != 0) { - DAT_TileMapState::instance.field213_0x554a48 - = DAT_TileMapState::instance.field213_0x554a48 | 0x8000; + _enemyNeighbourFlags = _enemyNeighbourFlags | 0x8000; } if ((*(uint*)((int)_occupancyRow + -2) & _teamBitFlags) != 0) { - DAT_TileMapState::instance.field213_0x554a48 - = DAT_TileMapState::instance.field213_0x554a48 | 0x2000; + _enemyNeighbourFlags = _enemyNeighbourFlags | 0x2000; } if ((*(uint*)((int)_occupancyRow + 2) & _teamBitFlags) != 0) { - DAT_TileMapState::instance.field213_0x554a48 - = DAT_TileMapState::instance.field213_0x554a48 | 0x20000; + _enemyNeighbourFlags = _enemyNeighbourFlags | 0x20000; } + DAT_TileMapState::instance.field213_0x554a48 = _enemyNeighbourFlags; for (_otherUnitID = (short)DAT_TileMapState::instance.UnitLayer[DAT_TileMapState::instance.DAT_SomeTile]; _otherUnitID > 0; _otherUnitID = (short)this->units[_otherUnitID].nextUnitOnTheSameTile) { diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 3695b61ac..db4d6a751 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -61405,7 +61405,7 @@ SHC_3BB0A8C1_0x00549B24 | 0.0% | Pending SHC_3BB0A8C1_0x00549B30 | 0.0% | Pending -SHC_3BB0A8C1_0x00549C70 | 20.3% | orig shares melee tail +SHC_3BB0A8C1_0x00549C70 | 29.2% | mask reg alloc, frame ptr SHC_3BB0A8C1_0x0054A770 | 100.0% | Reimplemented From eda9ce2798a5d84259214ef33ea43dce2ac69c99 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 15:29:12 +0200 Subject: [PATCH 197/299] reimplement: SHC_3BB0A8C1_0x00531920 25.58% extra spills, frame size --- .../UnitsState/processEntityDamageToUnit.cpp | 51 +++++++++---------- status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 24 insertions(+), 29 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/processEntityDamageToUnit.cpp b/src/OpenSHC/Map/Units/UnitsState/processEntityDamageToUnit.cpp index 5bbe4cf1b..0248cbb39 100644 --- a/src/OpenSHC/Map/Units/UnitsState/processEntityDamageToUnit.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/processEntityDamageToUnit.cpp @@ -17,6 +17,7 @@ #include "OpenSHC/Globals/DAT_GameSynchronyState.hpp" #include "OpenSHC/Globals/DAT_SFXState.hpp" #include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_UnitsState.hpp" #include "OpenSHC/Globals/DAT_TribesState.hpp" #include "OpenSHC/Globals/DAT_UnitPropertiesDefinedData.hpp" @@ -37,22 +38,18 @@ namespace Map { { short sVar3; - bool bVar4; + int bVar4; int _cowDiseaseDamage; - int _healthPercentage; - int _unitAltitude; - int _healthPercentage_2; uint uVar5; int _entityShootingUnitID_2; int _unitHeight; int _damage; eSFX sfxOffsetInArray; - bool _siegeProjectile; + int _siegeProjectile; short _entityShootingUnitID; EntityTypeShort _entityType; UnitTypeShort _entityType_2; - int* _unitHealth_ptr; - bool _unitIsSiegeEngine; + int _unitIsSiegeEngine; /* unclear what it does, but this function removes health from a unit, ranged @@ -60,13 +57,13 @@ namespace Map { */ int _unknown = (int)this->units[unitID].tribeID; - _unitIsSiegeEngine = false; - _siegeProjectile = false; - bVar4 = false; + _unitIsSiegeEngine = 0; + _siegeProjectile = 0; + bVar4 = 0; UnitTypeShort _unitType = this->units[unitID].unitType; _entityShootingUnitID = DAT_EntityState::instance.entityArray[entityID].unitID_OR_seaGullID; _entityShootingUnitID_2 = (int)_entityShootingUnitID; - if (unitID < 1) { + if (unitID <= 0) { return FALSE; } if (_entityShootingUnitID_2 == unitID) { @@ -87,7 +84,7 @@ namespace Map { if (this->units[unitID].dying != 0) { return FALSE; } - _entityShootingUnitID_2 = this->units[unitID].tile; + _entityShootingUnitID_2 = DAT_UnitsState::instance.units[unitID].tile; /* if the tile that the unit is on has some properties, don't bother either. */ @@ -144,8 +141,7 @@ namespace Map { /* * 80 */ _cowDiseaseDamage = (_cowDiseaseDamage * 0x50) / 100; } - _unitHealth_ptr = &this->units[unitID].health; - *_unitHealth_ptr = *_unitHealth_ptr - _cowDiseaseDamage; + this->units[unitID].health = this->units[unitID].health - _cowDiseaseDamage; if (this->units[unitID].health < 1) { this->units[unitID].health = 0; this->units[unitID].dying = 1; @@ -153,7 +149,7 @@ namespace Map { this->units[unitID].state.generic = OpenSHC::Map::Units::States::US_STONE_DEATH_02; this->units[unitID].tunnelerFinishedDigging = 1; } - _healthPercentage + int _healthPercentage = MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::DirectionAlgorithmState_Func::computeHealthPercentage, DAT_DirectionAlgorithmState::ptr)(this->units[unitID].health, this->units[unitID].maxHealth); this->units[unitID].healthPercentage = (short)_healthPercentage; @@ -162,26 +158,26 @@ namespace Map { } if (_unitType == OpenSHC::Map::Units::UT_S_TREBUCHET) { _unitHeight = (-(uint)(tileDistance != 0) & 0xffffffd8) + 0x50; - _unitIsSiegeEngine = true; + _unitIsSiegeEngine = 1; } else if (_unitType == OpenSHC::Map::Units::UT_S_TOWER) { _unitHeight = 0x50; - _unitIsSiegeEngine = true; + _unitIsSiegeEngine = 1; } else if (_unitType == OpenSHC::Map::Units::UT_S_CATAPULT) { _unitHeight = 0x32; - _unitIsSiegeEngine = true; + _unitIsSiegeEngine = 1; } else if (_unitType == OpenSHC::Map::Units::UT_S_SHIELD) { _unitHeight = 0x5a; - _unitIsSiegeEngine = true; + _unitIsSiegeEngine = 1; } else if (_unitType == OpenSHC::Map::Units::UT_S_BATTERINGRAM) { _unitHeight = 0x28; - _unitIsSiegeEngine = true; + _unitIsSiegeEngine = 1; } else if (_unitType == OpenSHC::Map::Units::UT_S_MANGONEL) { _unitHeight = 0x46; - _unitIsSiegeEngine = true; + _unitIsSiegeEngine = 1; } else { if ((_unitType == OpenSHC::Map::Units::UT_S_BALLISTA) || (_unitType == OpenSHC::Map::Units::UT_S_FBALLISTA)) { - _unitIsSiegeEngine = true; + _unitIsSiegeEngine = 1; } _unitHeight = 42; } @@ -190,7 +186,7 @@ namespace Map { || (_entityType == OpenSHC::Map::Entities::ET_MANGONEL)) || ((_entityType == OpenSHC::Map::Entities::ET_BALLISTA || (_entityType == OpenSHC::Map::Entities::ET_FIREBALLISTA)))) { - _siegeProjectile = true; + _siegeProjectile = 1; } short _unitPlayerID = this->units[unitID].owner; short _entityPlayerID = DAT_EntityState::instance.entityArray[entityID].owner; @@ -209,7 +205,7 @@ namespace Map { || (this->units[unitID].dying != 0)) { return FALSE; } - _unitAltitude = (int)this->units[unitID].terrainOrClimbHeight + (int)this->units[unitID].buildingHeight; + int _unitAltitude = (int)this->units[unitID].terrainOrClimbHeight + (int)this->units[unitID].buildingHeight; _damage = (int)DAT_EntityState::instance.entityArray[entityID].height; if (_damage < _unitAltitude) { return FALSE; @@ -352,8 +348,7 @@ namespace Map { _damage = _damage / 3; } } - _unitHealth_ptr = &this->units[unitID].health; - *_unitHealth_ptr = *_unitHealth_ptr - _damage; + this->units[unitID].health = this->units[unitID].health - _damage; if (this->units[unitID].health < 1) { this->units[unitID].health = 0; } @@ -377,7 +372,7 @@ namespace Map { = this->units[_entityShootingUnitID_2].uid; } int _unitHealth = this->units[unitID].health; - _healthPercentage_2 + int _healthPercentage_2 = MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::DirectionAlgorithmState_Func::computeHealthPercentage, DAT_DirectionAlgorithmState::ptr)(_unitHealth, this->units[unitID].maxHealth); _entityShootingUnitID = (short)_healthPercentage_2; @@ -388,7 +383,7 @@ namespace Map { || (_unitType == OpenSHC::Map::Units::UT_LADY)) || ((_unitType == OpenSHC::Map::Units::UT_MOTHER || ((_unitType == OpenSHC::Map::Units::UT_CHILD && (this->units[unitID].spriteID == 0x81)))))) { - bVar4 = true; + bVar4 = 1; } bool _shootingUnitID = this->units[_entityShootingUnitID_2].unitType == OpenSHC::Map::Units::UT_A_SLINGER; if ((_unitHealth < 1) && (this->units[unitID].dying == 0)) { diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index db4d6a751..0c06d6bc3 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -50075,7 +50075,7 @@ SHC_3BB0A8C1_0x00531914 | 0.0% | Pending SHC_3BB0A8C1_0x00531915 | 0.0% | Pending -SHC_3BB0A8C1_0x00531920 | 18.0% | orig merges pos blocks +SHC_3BB0A8C1_0x00531920 | 25.6% | extra spills, frame size SHC_3BB0A8C1_0x005323C0 | 0.0% | Pending From 519ee360139781245c2f47092ee625036ec87cb2 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 15:31:07 +0200 Subject: [PATCH 198/299] reimplement: SHC_3BB0A8C1_0x0054A7B0 34.28% reg alloc, spill order --- .../Map/Units/UnitsState/findNearestEnemyAndHeadTowardsIt.cpp | 4 ++-- status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/findNearestEnemyAndHeadTowardsIt.cpp b/src/OpenSHC/Map/Units/UnitsState/findNearestEnemyAndHeadTowardsIt.cpp index c99838308..f4cecf359 100644 --- a/src/OpenSHC/Map/Units/UnitsState/findNearestEnemyAndHeadTowardsIt.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/findNearestEnemyAndHeadTowardsIt.cpp @@ -27,8 +27,8 @@ namespace Map { { int _microX = this->units[unitID].microXPosition; int _microY = this->units[unitID].microYPosition; - short _playerID = this->units[unitID].owner; - ushort _area = DAT_TileMapState::instance.PathConnectionLayer[this->units[unitID].tile]; + int _playerID = this->units[unitID].owner; + int _area = DAT_TileMapState::instance.PathConnectionLayer[this->units[unitID].tile]; this->unitDistanceComputationResultUnk = 100000; dword _minDistance = 100000; dword _chosenRawDistance = 0; diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 0c06d6bc3..55ea6967c 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -61409,7 +61409,7 @@ SHC_3BB0A8C1_0x00549C70 | 29.2% | mask reg alloc, frame ptr SHC_3BB0A8C1_0x0054A770 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x0054A7B0 | 34.0% | orig walks enemy array ptr +SHC_3BB0A8C1_0x0054A7B0 | 34.3% | reg alloc, spill order SHC_3BB0A8C1_0x0054AA40 | 0.0% | Pending From 50fbd2d7d92008f3de132939cb5e8cb606bc0ee4 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 15:35:44 +0200 Subject: [PATCH 199/299] reimplement: SHC_3BB0A8C1_0x00531220 44.04% block order, reg alloc --- .../UnitsState/processUnitAttackOtherUnit.cpp | 37 +++++++++---------- status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 19 insertions(+), 20 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/processUnitAttackOtherUnit.cpp b/src/OpenSHC/Map/Units/UnitsState/processUnitAttackOtherUnit.cpp index 4bbe52bac..458b5abdc 100644 --- a/src/OpenSHC/Map/Units/UnitsState/processUnitAttackOtherUnit.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/processUnitAttackOtherUnit.cpp @@ -12,6 +12,7 @@ #include "OpenSHC/Globals/DAT_SoundSystemState.hpp" #include "OpenSHC/Globals/DAT_TribesState.hpp" #include "OpenSHC/Globals/DAT_UnitPropertiesDefinedData.hpp" +#include "OpenSHC/Globals/DAT_UnitsState.hpp" namespace OpenSHC { namespace Map { @@ -35,7 +36,7 @@ namespace Map { /* if unit 1 is not a lord */ if (this->units[unitID].unitType != OpenSHC::Map::Units::UT_LORD) { _damage = MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::computeDamageFearFactorBonus, this)( - _damage, this->units[unitID].owner); + _damage, DAT_UnitsState::instance.units[unitID].owner); } if (this->units[unitID].owner != 0 && this->units[unit2ID].owner != this->units[unitID].owner) { this->units[unit2ID].lastEncounteredEnemyPlayerID = this->units[unitID].owner; @@ -44,50 +45,48 @@ namespace Map { } /* decrement the health of unit 2 by damage */ this->units[unit2ID].health = this->units[unit2ID].health - _damage; - if (this->units[unit2ID].health < 1) { + if (this->units[unit2ID].health <= 0) { this->units[unit2ID].health = 0; } /* compute the health bar in percentages */ + short _healthPercentage; if (this->units[unit2ID].maxHealth == 0) { - this->units[unit2ID].healthPercentage = 100; + _healthPercentage = 100; } else { - this->units[unit2ID].healthPercentage - = (short)((this->units[unit2ID].health * 100) / this->units[unit2ID].maxHealth); + _healthPercentage = (short)((this->units[unit2ID].health * 100) / this->units[unit2ID].maxHealth); } - this->units[unit2ID].healthbar = this->units[unit2ID].healthPercentage / 10; + this->units[unit2ID].healthPercentage = _healthPercentage; + this->units[unit2ID].healthbar = _healthPercentage / 10; if (this->units[unit2ID].health <= 0 && this->units[unit2ID].isStalked != 0) { - eSFX _hitEffect; - bool _hasHitEffect = true; switch (this->units[unitID].unitType) { case OpenSHC::Map::Units::UT_WOODCUTTER: case OpenSHC::Map::Units::UT_LORD: - _hitEffect = OpenSHC::DE::SHCDE::FX_LORD_HIT; + MACRO_CALL_MEMBER(OpenSHC::Audio::SFX::SFXState_Func::playSFXAtLocation, DAT_SFXState::ptr)( + this->units[unitID].x, this->units[unitID].y, OpenSHC::DE::SHCDE::FX_LORD_HIT); break; case OpenSHC::Map::Units::UT_E_SPEAR: case OpenSHC::Map::Units::UT_A_ARCHER: case OpenSHC::Map::Units::UT_A_SLINGER: case OpenSHC::Map::Units::UT_A_HARCHER: case OpenSHC::Map::Units::UT_A_FIRETHROWER: - _hitEffect = OpenSHC::DE::SHCDE::FX_SPEAR_HIT; + MACRO_CALL_MEMBER(OpenSHC::Audio::SFX::SFXState_Func::playSFXAtLocation, DAT_SFXState::ptr)( + this->units[unitID].x, this->units[unitID].y, OpenSHC::DE::SHCDE::FX_SPEAR_HIT); break; case OpenSHC::Map::Units::UT_E_PIKE: - _hitEffect = OpenSHC::DE::SHCDE::FX_PIKE_HIT; + MACRO_CALL_MEMBER(OpenSHC::Audio::SFX::SFXState_Func::playSFXAtLocation, DAT_SFXState::ptr)( + this->units[unitID].x, this->units[unitID].y, OpenSHC::DE::SHCDE::FX_PIKE_HIT); break; case OpenSHC::Map::Units::UT_E_MACE: - _hitEffect = OpenSHC::DE::SHCDE::FX_MACE_HIT; + MACRO_CALL_MEMBER(OpenSHC::Audio::SFX::SFXState_Func::playSFXAtLocation, DAT_SFXState::ptr)( + this->units[unitID].x, this->units[unitID].y, OpenSHC::DE::SHCDE::FX_MACE_HIT); break; 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: - _hitEffect = OpenSHC::DE::SHCDE::FX_SWORD_HIT; - break; - default: - _hasHitEffect = false; - } - if (_hasHitEffect) { MACRO_CALL_MEMBER(OpenSHC::Audio::SFX::SFXState_Func::playSFXAtLocation, DAT_SFXState::ptr)( - this->units[unitID].x, this->units[unitID].y, _hitEffect); + this->units[unitID].x, this->units[unitID].y, OpenSHC::DE::SHCDE::FX_SWORD_HIT); + break; } } if (this->units[unit2ID].health > 0) { diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 55ea6967c..ba96cc1ef 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -49665,7 +49665,7 @@ SHC_3BB0A8C1_0x00531000 | 38.3% | orig caches unitTypes local SHC_3BB0A8C1_0x005311F0 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x00531220 | 31.0% | orig shares sfx tails +SHC_3BB0A8C1_0x00531220 | 44.0% | block order, reg alloc SHC_3BB0A8C1_0x00531814 | 0.0% | Pending From 148e4e6ac745d24adfe1a9166b53820c2df2a676 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 15:37:16 +0200 Subject: [PATCH 200/299] reimplement: SHC_3BB0A8C1_0x0053A5B0 11.38% arg push scheduling --- src/OpenSHC/Map/Units/UnitsState/renderDebugDataUnitData.cpp | 4 ++-- status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/renderDebugDataUnitData.cpp b/src/OpenSHC/Map/Units/UnitsState/renderDebugDataUnitData.cpp index 59d6b1a36..4014d77ef 100644 --- a/src/OpenSHC/Map/Units/UnitsState/renderDebugDataUnitData.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/renderDebugDataUnitData.cpp @@ -22,10 +22,10 @@ namespace Map { { int _selectedUnitID = this->lastSelectedUnitID; int _ownerID = this->units[_selectedUnitID].owner; - short _tribeID = this->units[_selectedUnitID].tribeID; + int _tribeID = this->units[_selectedUnitID].tribeID; int _lineY; int _column0 = x + 2; - if (_selectedUnitID < 1) { + if (_selectedUnitID <= 0) { MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( (char*)s_Not_watching_a_chimp_005abde0, _column0, y, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, FALSE, 0); diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index ba96cc1ef..618a9250c 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -59617,7 +59617,7 @@ SHC_3BB0A8C1_0x0053A4D0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0053A560 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x0053A5B0 | 9.8% | reg alloc, this on stack +SHC_3BB0A8C1_0x0053A5B0 | 11.4% | arg push scheduling SHC_3BB0A8C1_0x0053B1F0 | 0.0% | Pending From e79ee49b50b88eb69e575db9c52320b5044b9c38 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 15:43:47 +0200 Subject: [PATCH 201/299] reimplement: SHC_3BB0A8C1_0x0054B0D0 39.18% score tail, reg alloc --- src/OpenSHC/Map/Units/UnitsState/acquireShootTarget.cpp | 8 ++++---- status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/acquireShootTarget.cpp b/src/OpenSHC/Map/Units/UnitsState/acquireShootTarget.cpp index c8d6a30e9..2729861fb 100644 --- a/src/OpenSHC/Map/Units/UnitsState/acquireShootTarget.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/acquireShootTarget.cpp @@ -87,7 +87,7 @@ namespace Map { */ _entityType = 2; - if ((this->units[unitID].stoneAmmunition < 1) + if ((this->units[unitID].stoneAmmunition <= 0) && (this->units[unitID].targetingType != OpenSHC::Map::Units::UIT_THROW_COW)) { this->units[unitID].targetingType = OpenSHC::Map::Units::UIT_NO_INSTRUCTION_OR_MOVEUnk; return FALSE; @@ -99,7 +99,7 @@ namespace Map { */ _entityType = 3; - if ((this->units[unitID].stoneAmmunition < 1) + if ((this->units[unitID].stoneAmmunition <= 0) && (this->units[unitID].targetingType != OpenSHC::Map::Units::UIT_THROW_COW)) { this->units[unitID].targetingType = OpenSHC::Map::Units::UIT_NO_INSTRUCTION_OR_MOVEUnk; return FALSE; @@ -182,7 +182,7 @@ namespace Map { (int)((int)(*psVar2)), (int)((int)(*psVar1)), (int)((int)(this->units[_0x04_targetUnitID].buildingHeight + 0x1a + this->units[_0x04_targetUnitID].terrainOrClimbHeight))); - if (((_unitID < 1) + if (((_unitID <= 0) || (UVar4 = this->units[unitID].unitType, UVar4 == OpenSHC::Map::Units::UT_S_MANGONEL)) || (UVar4 == OpenSHC::Map::Units::UT_S_BALLISTA)) { if (this->units[unitID].unitType == OpenSHC::Map::Units::UT_HUNTER) { @@ -330,7 +330,7 @@ namespace Map { case OpenSHC::Map::Units::UT_RABBIT: _xDifferenceToTarget = (int)this->units[_unitID].tribeID; if (((this->units[_unitID].unitType == OpenSHC::Map::Units::UT_HUNTER) - || (_xDifferenceToTarget < 1)) + || (_xDifferenceToTarget <= 0)) || (DAT_TribesState::instance.tribes[_xDifferenceToTarget].field71_0x212 == 0)) continue; break; diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 618a9250c..052659733 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -61833,7 +61833,7 @@ SHC_3BB0A8C1_0x0054B0CB | 0.0% | Pending SHC_3BB0A8C1_0x0054B0CC | 0.0% | Pending -SHC_3BB0A8C1_0x0054B0D0 | 38.1% | score tail, reg alloc +SHC_3BB0A8C1_0x0054B0D0 | 39.2% | score tail, reg alloc SHC_3BB0A8C1_0x0054BE04 | 0.0% | Pending From ff697fba43c8f714ef995a57bacd0cf68ca2fc76 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 15:43:47 +0200 Subject: [PATCH 202/299] reimplement: SHC_3BB0A8C1_0x00533A10 29.51% reg alloc --- src/OpenSHC/Map/Units/UnitsState/computeLadderClimbPath.cpp | 2 +- status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/computeLadderClimbPath.cpp b/src/OpenSHC/Map/Units/UnitsState/computeLadderClimbPath.cpp index d42835760..a3e5a71cc 100644 --- a/src/OpenSHC/Map/Units/UnitsState/computeLadderClimbPath.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/computeLadderClimbPath.cpp @@ -31,7 +31,7 @@ namespace Map { int _pathPlanSize = MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::commitUnitPathPlanUsingWalkLayer, DAT_PathFindingState::ptr)(param_2, param_3, param_4); - if (_pathPlanSize < 1) { + if (_pathPlanSize <= 0) { return FALSE; } this->units[unitID].totalSizeOfPathPlan = (short)_pathPlanSize; diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 052659733..5208a1bb0 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -50685,7 +50685,7 @@ SHC_3BB0A8C1_0x005339A0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x005339F0 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x00533A10 | 19.5% | orig caches x/y in locals +SHC_3BB0A8C1_0x00533A10 | 29.5% | reg alloc SHC_3BB0A8C1_0x00533B30 | 70.1% | orig caches x/y in locals From b6ac40ec9e8b7d7f53f8c33199d984021f83f488 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 15:43:47 +0200 Subject: [PATCH 203/299] reimplement: SHC_3BB0A8C1_0x00536400 62.96% loop shape --- .../Units/UnitsState/countSelectedCatapultsAndTrebuchets.cpp | 2 +- status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/countSelectedCatapultsAndTrebuchets.cpp b/src/OpenSHC/Map/Units/UnitsState/countSelectedCatapultsAndTrebuchets.cpp index 632775141..8676985be 100644 --- a/src/OpenSHC/Map/Units/UnitsState/countSelectedCatapultsAndTrebuchets.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/countSelectedCatapultsAndTrebuchets.cpp @@ -18,7 +18,7 @@ namespace Map { { this->field15_0x560 = 0; if (DAT_GameState::instance.playerDataArray[DAT_GameSynchronyState::instance.currentPlayerSlotID].keep.id - < 1) { + <= 0) { return 0; } int _count = 0; diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 5208a1bb0..f71e19798 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -51125,7 +51125,7 @@ SHC_3BB0A8C1_0x00536310 | 0.0% | Pending SHC_3BB0A8C1_0x00536370 | 77.3% | cond order differs -SHC_3BB0A8C1_0x00536400 | 38.9% | branch shape differs +SHC_3BB0A8C1_0x00536400 | 63.0% | loop shape SHC_3BB0A8C1_0x00536440 | 0.0% | Pending From a1712f6f764cc810d2f9831dbfa71723793f1e16 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 15:43:48 +0200 Subject: [PATCH 204/299] reimplement: SHC_3BB0A8C1_0x0052E960 87.92% reg alloc --- src/OpenSHC/Map/Units/UnitsState/euroRecruit.cpp | 2 +- status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/euroRecruit.cpp b/src/OpenSHC/Map/Units/UnitsState/euroRecruit.cpp index 5d7dfa042..34394d3f3 100644 --- a/src/OpenSHC/Map/Units/UnitsState/euroRecruit.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/euroRecruit.cpp @@ -74,7 +74,7 @@ namespace Map { if (_horseResource == -1) { MACRO_CALL_MEMBER( OpenSHC::Game::GameStateStructures_Func::recountStablesAndHorses, DAT_GameState::ptr)(); - if (DAT_GameState::instance.playerDataArray[playerID].availableHorses < 1) { + if (DAT_GameState::instance.playerDataArray[playerID].availableHorses <= 0) { this->euroUnitAcquisitionFailReason = 4; return 0; } diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index f71e19798..2546a0312 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -49307,7 +49307,7 @@ SHC_3BB0A8C1_0x0052E7B0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0052E830 | 89.5% | orig walks unit ptr -SHC_3BB0A8C1_0x0052E960 | 83.3% | orig walks unit ptr +SHC_3BB0A8C1_0x0052E960 | 87.9% | reg alloc SHC_3BB0A8C1_0x0052EC10 | 100.0% | Reimplemented From b6519b606530f8f541a8187b6764ea29ca90fbbe Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 15:43:48 +0200 Subject: [PATCH 205/299] reimplement: SHC_3BB0A8C1_0x00537700 21.14% loop shape, spills --- src/OpenSHC/Map/Units/UnitsState/findTunnelTarget.cpp | 2 +- status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/findTunnelTarget.cpp b/src/OpenSHC/Map/Units/UnitsState/findTunnelTarget.cpp index 901277a63..a9380a014 100644 --- a/src/OpenSHC/Map/Units/UnitsState/findTunnelTarget.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/findTunnelTarget.cpp @@ -18,7 +18,7 @@ namespace Map { return FALSE; } int _distance; - if ((int)DAT_BuildingsState::instance.buildings[originBuildingID].tunnelerCounter < 1) { + if ((int)DAT_BuildingsState::instance.buildings[originBuildingID].tunnelerCounter <= 0) { _distance = 20; } else if ((int)DAT_BuildingsState::instance.buildings[originBuildingID].tunnelerCounter < 2) { _distance = 20; diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 2546a0312..26353f459 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -51235,7 +51235,7 @@ SHC_3BB0A8C1_0x005371E0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x005371F0 | 36.2% | orig walks XYPair ptrs -SHC_3BB0A8C1_0x00537700 | 16.1% | orig caches counter local +SHC_3BB0A8C1_0x00537700 | 21.1% | loop shape, spills SHC_3BB0A8C1_0x005377F0 | 100.0% | Reimplemented From c92eb58fc80cc9b3e80eea2cfe99ad72403df943 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 15:43:49 +0200 Subject: [PATCH 206/299] reimplement: SHC_3BB0A8C1_0x0053CAE0 48.61% reg alloc --- src/OpenSHC/Map/Units/UnitsState/getEnemyUnitIDNearby.cpp | 2 +- status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/getEnemyUnitIDNearby.cpp b/src/OpenSHC/Map/Units/UnitsState/getEnemyUnitIDNearby.cpp index 7de828372..01ac2f2a4 100644 --- a/src/OpenSHC/Map/Units/UnitsState/getEnemyUnitIDNearby.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/getEnemyUnitIDNearby.cpp @@ -33,7 +33,7 @@ namespace Map { } } _otherUnitID = (short)this->units[_otherUnitID].nextUnitOnTheSameTile; - if (_otherUnitID < 1) { + if (_otherUnitID <= 0) { return 0; } } diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 26353f459..de67abf66 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -59671,7 +59671,7 @@ SHC_3BB0A8C1_0x0053C590 | 0.0% | Pending SHC_3BB0A8C1_0x0053CAC0 | 0.0% | Pending -SHC_3BB0A8C1_0x0053CAE0 | 41.7% | loop shape differs +SHC_3BB0A8C1_0x0053CAE0 | 48.6% | reg alloc SHC_3BB0A8C1_0x0053CBD0 | 35.8% | orig caches shooter fields From 426995d3ce8fbe35e43e9f7cc540213053dde089 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 15:43:49 +0200 Subject: [PATCH 207/299] reimplement: SHC_3BB0A8C1_0x005300B0 26.19% Style pass, asm differs --- src/OpenSHC/Map/Units/UnitsState/playHurtSFXForUnit.cpp | 2 +- status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/playHurtSFXForUnit.cpp b/src/OpenSHC/Map/Units/UnitsState/playHurtSFXForUnit.cpp index b56891291..9c8d46ad0 100644 --- a/src/OpenSHC/Map/Units/UnitsState/playHurtSFXForUnit.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/playHurtSFXForUnit.cpp @@ -24,7 +24,7 @@ namespace Map { if (this->units[unitID].isStalked != 0) { return; } - if ((short)this->units[unitID].unitType < 1) { + if ((short)this->units[unitID].unitType <= 0) { return; } eSFX _sfxOffsetInArray; diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index de67abf66..dac790cc6 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -49363,7 +49363,7 @@ SHC_3BB0A8C1_0x0052FF80 | 67.5% | orig caches dir in locals SHC_3BB0A8C1_0x00530080 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x005300B0 | 25.0% | orig caches rng in local +SHC_3BB0A8C1_0x005300B0 | 26.2% | Style pass, asm differs SHC_3BB0A8C1_0x005301F0 | 96.0% | reg alloc differs From c12e2bb9759a6b0714b65d90598e419fc7c7cdae Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 15:43:50 +0200 Subject: [PATCH 208/299] reimplement: SHC_3BB0A8C1_0x00535BC0 57.91% Style pass, asm differs --- src/OpenSHC/Map/Units/UnitsState/playerMakeUnitSelection.cpp | 2 +- status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/playerMakeUnitSelection.cpp b/src/OpenSHC/Map/Units/UnitsState/playerMakeUnitSelection.cpp index 461b81a97..f581dd26b 100644 --- a/src/OpenSHC/Map/Units/UnitsState/playerMakeUnitSelection.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/playerMakeUnitSelection.cpp @@ -87,7 +87,7 @@ namespace Map { || _unitType == OpenSHC::Map::Units::UT_S_TREBUCHET) { if ((this->units[_siegeEngineUnitID].unitType == OpenSHC::Map::Units::UT_S_CATAPULT || this->units[_siegeEngineUnitID].unitType == OpenSHC::Map::Units::UT_S_TREBUCHET) - && this->units[_siegeEngineUnitID].stoneAmmunition < 1) { + && this->units[_siegeEngineUnitID].stoneAmmunition <= 0) { MACRO_CALL_MEMBER(OpenSHC::Audio::SFX::SFXState_Func::playSpeechSFX, DAT_SFXState::ptr)( OpenSHC::Audio::SFX::SEID_RESOURCE_NEED25); DAT_UIDragDropDefinedData::instance.MenuView_TriggerInitial = TRUE; diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index dac790cc6..9a6547370 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -51101,7 +51101,7 @@ SHC_3BB0A8C1_0x00535A30 | 67.7% | call+reg alloc differs SHC_3BB0A8C1_0x00535B00 | 61.8% | call+reg alloc differs -SHC_3BB0A8C1_0x00535BC0 | 47.2% | branch shape differs +SHC_3BB0A8C1_0x00535BC0 | 57.9% | Style pass, asm differs SHC_3BB0A8C1_0x00535DF0 | 46.1% | call+reg alloc differs From 5c0ed203f52b08cf36801e91fbfb4a6e92d45d4a Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 15:43:50 +0200 Subject: [PATCH 209/299] reimplement: SHC_3BB0A8C1_0x0053CBD0 37.21% reg alloc --- src/OpenSHC/Map/Units/UnitsState/prepareProjectileTarget.cpp | 2 +- status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/prepareProjectileTarget.cpp b/src/OpenSHC/Map/Units/UnitsState/prepareProjectileTarget.cpp index a4cdcfe9c..14fccd1b7 100644 --- a/src/OpenSHC/Map/Units/UnitsState/prepareProjectileTarget.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/prepareProjectileTarget.cpp @@ -117,7 +117,7 @@ namespace Map { case OpenSHC::Map::Units::UT_S_FBALLISTA: return _result; } - if (_scatter < 1) { + if (_scatter <= 0) { return _result; } if (_scatter > 0x118) { diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 9a6547370..ec2f0b36e 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -59673,7 +59673,7 @@ SHC_3BB0A8C1_0x0053CAC0 | 0.0% | Pending SHC_3BB0A8C1_0x0053CAE0 | 48.6% | reg alloc -SHC_3BB0A8C1_0x0053CBD0 | 35.8% | orig caches shooter fields +SHC_3BB0A8C1_0x0053CBD0 | 37.2% | reg alloc SHC_3BB0A8C1_0x0053CF84 | 0.0% | Pending From 00652291569e265d5cacf99c0d15f12b5c1cb1bc Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 15:43:50 +0200 Subject: [PATCH 210/299] reimplement: SHC_3BB0A8C1_0x00532460 75.85% reg alloc --- src/OpenSHC/Map/Units/UnitsState/processFireDamageToUnit.cpp | 4 ++-- status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/processFireDamageToUnit.cpp b/src/OpenSHC/Map/Units/UnitsState/processFireDamageToUnit.cpp index 41ccac893..af551a3ea 100644 --- a/src/OpenSHC/Map/Units/UnitsState/processFireDamageToUnit.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/processFireDamageToUnit.cpp @@ -21,7 +21,7 @@ namespace Map { // FUNCTION: STRONGHOLDCRUSADER 0x00532460 undefined4 UnitsState::processFireDamageToUnit(int unitID, int playerID, int halfTheDamage) { - if (unitID < 1) { + if (unitID <= 0) { return 0; } if (this->units[unitID].dying != 0) { @@ -46,7 +46,7 @@ namespace Map { this->units[unitID].lastEncounteredEnemyUnitIDUnk = 0; } this->units[unitID].health = this->units[unitID].health - _damage; - if (this->units[unitID].health < 1) { + if (this->units[unitID].health <= 0) { this->units[unitID].health = 0; } if (this->units[unitID].maxHealth == 0) { diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index ec2f0b36e..b7f4cd0a6 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -50331,7 +50331,7 @@ SHC_3BB0A8C1_0x0053245D | 0.0% | Pending SHC_3BB0A8C1_0x0053245E | 0.0% | Pending -SHC_3BB0A8C1_0x00532460 | 66.2% | branch shape differs +SHC_3BB0A8C1_0x00532460 | 75.8% | reg alloc SHC_3BB0A8C1_0x005326A8 | 0.0% | Pending From aa826293ee506f9450969b12433cc30321a02d59 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 15:43:51 +0200 Subject: [PATCH 211/299] reimplement: SHC_3BB0A8C1_0x00549C70 29.20% Style pass, asm differs --- src/OpenSHC/Map/Units/UnitsState/processMeleeInitiation.cpp | 4 ++-- status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/processMeleeInitiation.cpp b/src/OpenSHC/Map/Units/UnitsState/processMeleeInitiation.cpp index 998361023..607d656d9 100644 --- a/src/OpenSHC/Map/Units/UnitsState/processMeleeInitiation.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/processMeleeInitiation.cpp @@ -42,7 +42,7 @@ namespace Map { && (this->units[unitID].dying == 0)) && (this->units[unitID].moveRelatedFlag != 1)))) { int _distanceThreshold; - if (this->units[unitID].stateBasedSpeed < 1) { + if (this->units[unitID].stateBasedSpeed <= 0) { /* 50 or 150 depending on selectable */ @@ -514,7 +514,7 @@ namespace Map { } _otherUnitID = MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::getEnemyUnitIDNearby, this)(unitID, _candidateTile, _totalHeight); - if (_otherUnitID < 1) { + if (_otherUnitID <= 0) { continue; } if (this->units[_otherUnitID].logicalState != OpenSHC::Map::Units::ULS_NORMAL) { diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index b7f4cd0a6..bbf6b842a 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -61405,7 +61405,7 @@ SHC_3BB0A8C1_0x00549B24 | 0.0% | Pending SHC_3BB0A8C1_0x00549B30 | 0.0% | Pending -SHC_3BB0A8C1_0x00549C70 | 29.2% | mask reg alloc, frame ptr +SHC_3BB0A8C1_0x00549C70 | 29.2% | Style pass, asm differs SHC_3BB0A8C1_0x0054A770 | 100.0% | Reimplemented From f61389a921d896d9b27a00de705b1e635b2ad1d8 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 15:43:51 +0200 Subject: [PATCH 212/299] reimplement: SHC_3BB0A8C1_0x0052F010 100.00% Reimplemented --- src/OpenSHC/Map/Units/UnitsState/removeUnitFromItsTribe.cpp | 4 ++-- status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/removeUnitFromItsTribe.cpp b/src/OpenSHC/Map/Units/UnitsState/removeUnitFromItsTribe.cpp index cbd03c775..5350396a2 100644 --- a/src/OpenSHC/Map/Units/UnitsState/removeUnitFromItsTribe.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/removeUnitFromItsTribe.cpp @@ -15,7 +15,7 @@ namespace Map { // FUNCTION: STRONGHOLDCRUSADER 0x0052F010 void UnitsState::removeUnitFromItsTribe(uint unitID, int unitUID) { - if ((int)unitID < 1) { + if ((int)unitID <= 0) { return; } if (this->units[unitID].uid != unitUID) { @@ -23,7 +23,7 @@ namespace Map { } int _tribeID = this->units[unitID].tribeID; this->units[unitID].logicalState = OpenSHC::Map::Units::ULS_REMOVE; - if (_tribeID < 1) { + if (_tribeID <= 0) { return; } if (MACRO_CALL_MEMBER(OpenSHC::Map::Units::TribesState_Func::tribeCorrespondsWithUID, DAT_TribesState::ptr)( diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index bbf6b842a..c7ca203d8 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -49315,7 +49315,7 @@ SHC_3BB0A8C1_0x0052EDC0 | 48.5% | branch shape differs SHC_3BB0A8C1_0x0052EED0 | 80.0% | orig caches unitType local -SHC_3BB0A8C1_0x0052F010 | 69.0% | branch shape differs +SHC_3BB0A8C1_0x0052F010 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0052F070 | 100.0% | Reimplemented From 848730c4ddca137d1b61e52db5f09bb731aceeba Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 15:43:52 +0200 Subject: [PATCH 213/299] reimplement: SHC_3BB0A8C1_0x0052F730 82.83% reg alloc --- .../removeUnitsSameTileLinkageIfNoLongerApplicable.cpp | 2 +- status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/removeUnitsSameTileLinkageIfNoLongerApplicable.cpp b/src/OpenSHC/Map/Units/UnitsState/removeUnitsSameTileLinkageIfNoLongerApplicable.cpp index 2fc4c0a5a..45834df88 100644 --- a/src/OpenSHC/Map/Units/UnitsState/removeUnitsSameTileLinkageIfNoLongerApplicable.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/removeUnitsSameTileLinkageIfNoLongerApplicable.cpp @@ -10,7 +10,7 @@ namespace Map { // FUNCTION: STRONGHOLDCRUSADER 0x0052F730 void UnitsState::removeUnitsSameTileLinkageIfNoLongerApplicable() { - if (DAT_GameState::instance.mapAndTime.multiplayerUnitSameTileLinkageTimeWindow < 1) { + if (DAT_GameState::instance.mapAndTime.multiplayerUnitSameTileLinkageTimeWindow <= 0) { DAT_GameState::instance.mapAndTime.multiplayerUnitSameTileLinkageTimeWindow = 0; return; } diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index c7ca203d8..19f45dc28 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -49341,7 +49341,7 @@ SHC_3BB0A8C1_0x0052F680 | 58.3% | branch shape differs SHC_3BB0A8C1_0x0052F6C0 | 0.0% | Pending -SHC_3BB0A8C1_0x0052F730 | 45.4% | branch shape differs +SHC_3BB0A8C1_0x0052F730 | 82.8% | reg alloc SHC_3BB0A8C1_0x0052F7E0 | 17.6% | orig caches height locals From bd81567a5af72db0c54434f154927f4fd3f869a3 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 15:43:52 +0200 Subject: [PATCH 214/299] reimplement: SHC_3BB0A8C1_0x00535E20 65.08% reg alloc --- .../Map/Units/UnitsState/selectSiegeEngineAndPlayFeedback.cpp | 2 +- status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/selectSiegeEngineAndPlayFeedback.cpp b/src/OpenSHC/Map/Units/UnitsState/selectSiegeEngineAndPlayFeedback.cpp index 0b3ca49b6..cb1d46d73 100644 --- a/src/OpenSHC/Map/Units/UnitsState/selectSiegeEngineAndPlayFeedback.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/selectSiegeEngineAndPlayFeedback.cpp @@ -65,7 +65,7 @@ namespace Map { } if ((_unitType == OpenSHC::Map::Units::UT_S_CATAPULT || _unitType == OpenSHC::Map::Units::UT_S_TREBUCHET) - && this->units[_siegeEngineUnitID].stoneAmmunition < 1) { + && this->units[_siegeEngineUnitID].stoneAmmunition <= 0) { MACRO_CALL_MEMBER(OpenSHC::Audio::SFX::SFXState_Func::playSpeechSFX, DAT_SFXState::ptr)( OpenSHC::Audio::SFX::SEID_RESOURCE_NEED25); DAT_UIDragDropDefinedData::instance.MenuView_TriggerInitial = TRUE; diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 19f45dc28..f97c46786 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -51105,7 +51105,7 @@ SHC_3BB0A8C1_0x00535BC0 | 57.9% | Style pass, asm differs SHC_3BB0A8C1_0x00535DF0 | 46.1% | call+reg alloc differs -SHC_3BB0A8C1_0x00535E20 | 40.0% | branch shape differs +SHC_3BB0A8C1_0x00535E20 | 65.1% | reg alloc SHC_3BB0A8C1_0x00535FD0 | 88.9% | orig walks hotkey ptr From 9cd4b0d4c191adc8588d7b7ccabe631d5058d129 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 15:43:53 +0200 Subject: [PATCH 215/299] reimplement: SHC_3BB0A8C1_0x0052FE00 100.00% Reimplemented --- .../Map/Units/UnitsState/setFacingDirectionTowardUnitMicro.cpp | 2 +- status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/setFacingDirectionTowardUnitMicro.cpp b/src/OpenSHC/Map/Units/UnitsState/setFacingDirectionTowardUnitMicro.cpp index 1e75ea082..5b93d37db 100644 --- a/src/OpenSHC/Map/Units/UnitsState/setFacingDirectionTowardUnitMicro.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/setFacingDirectionTowardUnitMicro.cpp @@ -13,7 +13,7 @@ namespace Map { // FUNCTION: STRONGHOLDCRUSADER 0x0052FE00 void UnitsState::setFacingDirectionTowardUnitMicro(int unitID, int targetUnitID) { - if (targetUnitID < 1) { + if (targetUnitID <= 0) { return; } MACRO_CALL_MEMBER( diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index f97c46786..ba52ba00d 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -49355,7 +49355,7 @@ SHC_3BB0A8C1_0x0052FCA0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0052FD00 | 83.1% | orig caches dir in locals -SHC_3BB0A8C1_0x0052FE00 | 84.8% | reg alloc differs +SHC_3BB0A8C1_0x0052FE00 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0052FE90 | 81.9% | orig caches dir in locals From ba351d9a0cea76042f8500da64a5577a9b0cc6bd Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 15:43:53 +0200 Subject: [PATCH 216/299] reimplement: SHC_3BB0A8C1_0x0052FD00 90.14% reg alloc --- .../Units/UnitsState/setUnitFacingDirectionTowardsTarget.cpp | 2 +- status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/setUnitFacingDirectionTowardsTarget.cpp b/src/OpenSHC/Map/Units/UnitsState/setUnitFacingDirectionTowardsTarget.cpp index 451b56c2e..1e2ebfcce 100644 --- a/src/OpenSHC/Map/Units/UnitsState/setUnitFacingDirectionTowardsTarget.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/setUnitFacingDirectionTowardsTarget.cpp @@ -11,7 +11,7 @@ namespace Map { // FUNCTION: STRONGHOLDCRUSADER 0x0052FD00 undefined4 UnitsState::setUnitFacingDirectionTowardsTarget(int unitID, int targetUnitID) { - if (targetUnitID < 1) { + if (targetUnitID <= 0) { return 0; } MACRO_CALL_MEMBER( diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index ba52ba00d..a65bb2734 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -49353,7 +49353,7 @@ SHC_3BB0A8C1_0x0052FC30 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0052FCA0 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x0052FD00 | 83.1% | orig caches dir in locals +SHC_3BB0A8C1_0x0052FD00 | 90.1% | reg alloc SHC_3BB0A8C1_0x0052FE00 | 100.0% | Reimplemented From a5fc84aebf299275a51e0c8f5b0789ee7e8cd180 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 15:43:53 +0200 Subject: [PATCH 217/299] reimplement: SHC_3BB0A8C1_0x0053B8E0 86.89% reg alloc --- src/OpenSHC/Map/Units/UnitsState/setUnitValues.cpp | 2 +- status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/setUnitValues.cpp b/src/OpenSHC/Map/Units/UnitsState/setUnitValues.cpp index c0f7a7df0..fe64c4757 100644 --- a/src/OpenSHC/Map/Units/UnitsState/setUnitValues.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/setUnitValues.cpp @@ -62,7 +62,7 @@ namespace Map { || unitType == OpenSHC::Map::Units::UT_FIREEATER || unitType == OpenSHC::Map::Units::UT_PRIEST) { MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::assignNameToUnit, this)(unitID); } - if (this->units[unitID].owner < 1) { + if (this->units[unitID].owner <= 0) { this->units[unitID].occupancyOrFlag = 0xff; this->units[unitID].field258_0x3d1 = 0xff; } else { diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index a65bb2734..881198921 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -59651,7 +59651,7 @@ SHC_3BB0A8C1_0x0053B800 | 0.0% | Pending SHC_3BB0A8C1_0x0053B8B0 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x0053B8E0 | 83.6% | orig caches many locals +SHC_3BB0A8C1_0x0053B8E0 | 86.9% | reg alloc SHC_3BB0A8C1_0x0053BB10 | 100.0% | Reimplemented From 2e563aca910a18ceb9342d2b7902fa0f3aaf1a41 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 15:43:54 +0200 Subject: [PATCH 218/299] reimplement: SHC_3BB0A8C1_0x00537D60 48.72% reg alloc --- src/OpenSHC/Map/Units/UnitsState/tryAttackUnitID.cpp | 2 +- status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/tryAttackUnitID.cpp b/src/OpenSHC/Map/Units/UnitsState/tryAttackUnitID.cpp index f4932e4b2..5b8264a9e 100644 --- a/src/OpenSHC/Map/Units/UnitsState/tryAttackUnitID.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/tryAttackUnitID.cpp @@ -14,7 +14,7 @@ namespace Map { // FUNCTION: STRONGHOLDCRUSADER 0x00537D60 undefined4 UnitsState::tryAttackUnitID(int unitID_1, int unitID_2) { - if (unitID_2 < 1) { + if (unitID_2 <= 0) { return 0; } if (this->units[unitID_1].logicalState != OpenSHC::Map::Units::ULS_NORMAL) { diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 881198921..5a5126965 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -51257,7 +51257,7 @@ SHC_3BB0A8C1_0x00537C10 | 48.5% | orig walks unit ptr SHC_3BB0A8C1_0x00537C90 | 0.0% | Pending -SHC_3BB0A8C1_0x00537D60 | 14.6% | orig uses global instance +SHC_3BB0A8C1_0x00537D60 | 48.7% | reg alloc SHC_3BB0A8C1_0x00537E00 | 35.2% | orig has 2 separate loops From b709f6fe6bffe987b3c095609772420605963c8e Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 15:43:54 +0200 Subject: [PATCH 219/299] reimplement: SHC_3BB0A8C1_0x00579300 33.71% Style pass, asm differs --- src/OpenSHC/Map/Units/UnitsState/updateUnits.cpp | 2 +- status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/updateUnits.cpp b/src/OpenSHC/Map/Units/UnitsState/updateUnits.cpp index 25b8e95ae..7eb330753 100644 --- a/src/OpenSHC/Map/Units/UnitsState/updateUnits.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/updateUnits.cpp @@ -666,7 +666,7 @@ namespace Map { < _troopValue - this->units[DAT_CurrentUnitSlotID::instance].field199_0x350) { this->units[DAT_CurrentUnitSlotID::instance].field199_0x350 = _troopValue; psVar4 = &this->units[DAT_CurrentUnitSlotID::instance].movementRunUpTime; - if (this->units[DAT_CurrentUnitSlotID::instance].movementRunUpTime < 1) { + if (this->units[DAT_CurrentUnitSlotID::instance].movementRunUpTime <= 0) { *psVar4 = 0; } else { *psVar4 = *psVar4 + -1; diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 5a5126965..dff2e86e8 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -66991,7 +66991,7 @@ SHC_3BB0A8C1_0x005792F8 | 0.0% | Pending SHC_3BB0A8C1_0x005792FC | 0.0% | Pending -SHC_3BB0A8C1_0x00579300 | 28.5% | reg alloc, dup tails +SHC_3BB0A8C1_0x00579300 | 33.7% | Style pass, asm differs SHC_3BB0A8C1_0x00579380 | 0.0% | Pending From 6e2a0e292e39aea21a3b88738b852abe543cf05e Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 15:59:32 +0200 Subject: [PATCH 220/299] reimplement: SHC_3BB0A8C1_0x00535240 75.53% switch case order --- .../UnitsState/recountUnitsInSelection.cpp | 36 ++++--------------- status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 7 insertions(+), 31 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/recountUnitsInSelection.cpp b/src/OpenSHC/Map/Units/UnitsState/recountUnitsInSelection.cpp index 0f8f4c101..1fbc5acdf 100644 --- a/src/OpenSHC/Map/Units/UnitsState/recountUnitsInSelection.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/recountUnitsInSelection.cpp @@ -12,33 +12,9 @@ namespace Map { // FUNCTION: STRONGHOLDCRUSADER 0x00535240 void UnitsState::recountUnitsInSelection() { - this->selectionEuropeanArchers = 0; - this->selectionSpearmen = 0; - this->selectionMacemen = 0; - this->selectionCrossbowmen = 0; - this->selectionPikemen = 0; - this->selectionSwordsmen = 0; - this->selectionKnights = 0; - this->selectionEngineers = 0; - this->selectionLaddermen = 0; - this->selectionTunnelers = 0; - this->selectionMonks = 0; - this->selectionCatapults = 0; - this->selectionTrebuchets = 0; - this->selectionBatteringRam = 0; - this->selectionSiegeTower = 0; - this->selectionShield = 0; - this->selectionMangonel = 0; - this->selectionBallista = 0; - this->nSelectionFireBallistas = 0; - this->selectionArabArcher = 0; - this->selectionArabSlave = 0; - this->selectionArabSlinger = 0; - this->selectionArabAssassin = 0; - this->selectionArabHorseArchers = 0; - this->selectionArabSwordsman = 0; - this->selectionArabFireThrower = 0; - this->selectionFireBallista = 0; + for (int i = 0; i <= 26; ++i) { + (&this->selectionEuropeanArchers)[i] = 0; + } for (int unitID = 1; unitID < (int)this->maxUnitCount; ++unitID) { if (this->units[unitID].logicalState != OpenSHC::Map::Units::ULS_NORMAL) { continue; @@ -53,9 +29,6 @@ namespace Map { continue; } switch (this->units[unitID].unitType) { - case OpenSHC::Map::Units::UT_TUNNELER: - this->selectionTunnelers = this->selectionTunnelers + 1; - break; case OpenSHC::Map::Units::UT_E_ARCHER: this->selectionEuropeanArchers = this->selectionEuropeanArchers + 1; break; @@ -86,6 +59,9 @@ namespace Map { case OpenSHC::Map::Units::UT_E_MONK: this->selectionMonks = this->selectionMonks + 1; break; + case OpenSHC::Map::Units::UT_TUNNELER: + this->selectionTunnelers = this->selectionTunnelers + 1; + break; case OpenSHC::Map::Units::UT_S_CATAPULT: this->selectionCatapults = this->selectionCatapults + 1; break; diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index dff2e86e8..d2780815e 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -50863,7 +50863,7 @@ SHC_3BB0A8C1_0x005351C0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00535200 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x00535240 | 35.1% | orig walks counter ptr +SHC_3BB0A8C1_0x00535240 | 75.5% | switch case order SHC_3BB0A8C1_0x00535460 | 0.0% | Pending From b420a77ba48f1ac1ef640e648a31cabe341d14ef Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 16:02:20 +0200 Subject: [PATCH 221/299] reimplement: SHC_3BB0A8C1_0x0053A150 56.87% reg alloc, spill order --- .../getWorkerBlockingStateIfStuck.cpp | 55 ++++++++++--------- status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 29 insertions(+), 28 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/getWorkerBlockingStateIfStuck.cpp b/src/OpenSHC/Map/Units/UnitsState/getWorkerBlockingStateIfStuck.cpp index dc37cbe17..0bb06978a 100644 --- a/src/OpenSHC/Map/Units/UnitsState/getWorkerBlockingStateIfStuck.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/getWorkerBlockingStateIfStuck.cpp @@ -18,15 +18,16 @@ namespace Map { // FUNCTION: STRONGHOLDCRUSADER 0x0053A150 int UnitsState::getWorkerBlockingStateIfStuck(int unitID) { + int _state = this->units[unitID].state.generic; if (this->units[unitID].dying != 0) { return 0; } switch (this->units[unitID].unitType) { case OpenSHC::Map::Units::UT_WOODCUTTER: - if (this->units[unitID].state.generic == OpenSHC::Map::Units::States::US_LOOK_AROUNDUnk) { + if (_state == OpenSHC::Map::Units::States::US_LOOK_AROUNDUnk) { return 0x2f; } - if (this->units[unitID].state.generic == (UnitState)10) { + if (_state == (UnitState)10) { if (MACRO_CALL_MEMBER(OpenSHC::Map::LandscapeState_Func::findTree, DAT_LandscapeState::ptr)( this->units[unitID].owner, this->units[unitID].x, this->units[unitID].y) != 0) { @@ -36,10 +37,10 @@ namespace Map { } break; case OpenSHC::Map::Units::UT_FLETCHER: - if (this->units[unitID].state.generic == OpenSHC::Map::Units::States::US_FIRE_WEAPONUnk) { + if (_state == OpenSHC::Map::Units::States::US_FIRE_WEAPONUnk) { return 0x31; } - if (this->units[unitID].state.generic != OpenSHC::Map::Units::States::US_STAND_UPUnk) { + if (_state != OpenSHC::Map::Units::States::US_STAND_UPUnk) { return 0; } if (MACRO_CALL_MEMBER( @@ -50,10 +51,10 @@ namespace Map { } return 0x33; case OpenSHC::Map::Units::UT_HUNTER: - if (this->units[unitID].state.generic == OpenSHC::Map::Units::States::US_RELOAD_WEAPONUnk) { + if (_state == OpenSHC::Map::Units::States::US_RELOAD_WEAPONUnk) { return 0x30; } - if (this->units[unitID].state.generic == OpenSHC::Map::Units::States::US_LOOK_AROUNDUnk) { + if (_state == OpenSHC::Map::Units::States::US_LOOK_AROUNDUnk) { if (MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::findNearestShootableDeer, this)(unitID) != 0) { return 0; @@ -63,33 +64,33 @@ namespace Map { break; case OpenSHC::Map::Units::UT_QUARRYWORKER: case OpenSHC::Map::Units::UT_PITCHMAN: - if (this->units[unitID].state.generic == (UnitState)2) { + if (_state == (UnitState)2) { return 0x2f; } break; case OpenSHC::Map::Units::UT_WHEATFARMER: - if (this->units[unitID].state.generic + if (_state == (OpenSHC::Map::Units::States::US_STAND_UPUnk | OpenSHC::Map::Units::States::US_IDLEUnk)) { return 0x2f; } break; case OpenSHC::Map::Units::UT_HOPSFARMER: - if (this->units[unitID].state.generic == OpenSHC::Map::Units::States::US_LOOK_AROUNDUnk) { + if (_state == OpenSHC::Map::Units::States::US_LOOK_AROUNDUnk) { return 0x2f; } break; case OpenSHC::Map::Units::UT_APPLEFARMER: - if (this->units[unitID].state.generic == OpenSHC::Map::Units::States::US_FIRE_WEAPONUnk) { + if (_state == OpenSHC::Map::Units::States::US_FIRE_WEAPONUnk) { return 0x30; } break; case OpenSHC::Map::Units::UT_DAIRYFARMER: - if (this->units[unitID].state.generic == OpenSHC::Map::Units::States::US_RELOAD_WEAPONUnk) { + if (_state == OpenSHC::Map::Units::States::US_RELOAD_WEAPONUnk) { return 0x30; } break; case OpenSHC::Map::Units::UT_MILLER: - if (this->units[unitID].state.generic == OpenSHC::Map::Units::States::US_IDLEUnk) { + if (_state == OpenSHC::Map::Units::States::US_IDLEUnk) { if (MACRO_CALL_MEMBER( OpenSHC::Map::Buildings::BuildingsState_Func::getStorageBuildingForResourceTypeAndAmount, DAT_BuildingsState::ptr)(OpenSHC::Game::Resources::RT_WHEAT, 1, this->units[unitID].owner) @@ -98,15 +99,15 @@ namespace Map { } return 0x35; } - if (this->units[unitID].state.generic == OpenSHC::Map::Units::States::US_LOOK_AROUNDUnk) { + if (_state == OpenSHC::Map::Units::States::US_LOOK_AROUNDUnk) { return 0x2f; } break; case OpenSHC::Map::Units::UT_BAKER: - if ((short)this->units[unitID].state.generic < 0) { + if (_state < 0) { break; } - if ((short)this->units[unitID].state.generic < 2) { + if (_state < 2) { if (MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::getBuildingResourceAmountByUid, DAT_BuildingsState::ptr)(this->units[DAT_CurrentUnitSlotID::instance].workplaceBuildingID_1, DAT_BuildingsState::instance @@ -118,12 +119,12 @@ namespace Map { } return 0x36; } - if (this->units[unitID].state.generic == OpenSHC::Map::Units::States::US_AIM_WEAPONUnk) { + if (_state == OpenSHC::Map::Units::States::US_AIM_WEAPONUnk) { return 0x30; } break; case OpenSHC::Map::Units::UT_BREWER: - if (this->units[unitID].state.generic == OpenSHC::Map::Units::States::US_IDLEUnk) { + if (_state == OpenSHC::Map::Units::States::US_IDLEUnk) { if (MACRO_CALL_MEMBER( OpenSHC::Map::Buildings::BuildingsState_Func::getStorageBuildingForResourceTypeAndAmount, DAT_BuildingsState::ptr)( @@ -133,12 +134,12 @@ namespace Map { } return 0x37; } - if (this->units[unitID].state.generic == OpenSHC::Map::Units::States::US_LOOK_AROUNDUnk) { + if (_state == OpenSHC::Map::Units::States::US_LOOK_AROUNDUnk) { return 0x2f; } break; case OpenSHC::Map::Units::UT_POLETURNER: - if (this->units[unitID].state.generic == OpenSHC::Map::Units::States::US_IDLEUnk) { + if (_state == OpenSHC::Map::Units::States::US_IDLEUnk) { if (MACRO_CALL_MEMBER( OpenSHC::Map::Buildings::BuildingsState_Func::getStorageBuildingForResourceTypeAndAmount, DAT_BuildingsState::ptr)(OpenSHC::Game::Resources::RT_WOOD, 1, this->units[unitID].owner) @@ -147,17 +148,17 @@ namespace Map { } return 0x33; } - if (this->units[unitID].state.generic == OpenSHC::Map::Units::States::US_LOOK_AROUNDUnk) { + if (_state == OpenSHC::Map::Units::States::US_LOOK_AROUNDUnk) { return 0x31; } break; case OpenSHC::Map::Units::UT_SMITH: case OpenSHC::Map::Units::UT_ARMORER: - if (this->units[unitID].state.generic != OpenSHC::Map::Units::States::US_IDLEUnk) { - if (this->units[unitID].state.generic == OpenSHC::Map::Units::States::US_LOOK_AROUNDUnk) { + if (_state != OpenSHC::Map::Units::States::US_IDLEUnk) { + if (_state == OpenSHC::Map::Units::States::US_LOOK_AROUNDUnk) { return 0x31; } - if (this->units[unitID].state.generic + if (_state != (OpenSHC::Map::Units::States::US_STAND_UPUnk | OpenSHC::Map::Units::States::US_IDLEUnk)) { return 0; } @@ -170,7 +171,7 @@ namespace Map { } return 0x38; case OpenSHC::Map::Units::UT_TANNER: - if (this->units[unitID].state.generic == OpenSHC::Map::Units::States::US_IDLEUnk) { + if (_state == OpenSHC::Map::Units::States::US_IDLEUnk) { if (MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::findNearestIdleCowForPlayer, this)( this->units[unitID].owner, this->units[unitID].x, this->units[unitID].y) != 0) { @@ -178,17 +179,17 @@ namespace Map { } return 0x39; } - if (this->units[unitID].state.generic == OpenSHC::Map::Units::States::US_LOOK_AROUNDUnk) { + if (_state == OpenSHC::Map::Units::States::US_LOOK_AROUNDUnk) { return 0x31; } break; case OpenSHC::Map::Units::UT_TRANSPORTMINER: - if (this->units[unitID].state.generic == (UnitState)3) { + if (_state == (UnitState)3) { return 0x2f; } break; case OpenSHC::Map::Units::UT_INNKEEPER: - if (this->units[unitID].state.generic == OpenSHC::Map::Units::States::US_IDLEUnk) { + if (_state == OpenSHC::Map::Units::States::US_IDLEUnk) { if (MACRO_CALL_MEMBER( OpenSHC::Map::Buildings::BuildingsState_Func::getStorageBuildingForResourceTypeAndAmount, DAT_BuildingsState::ptr)(OpenSHC::Game::Resources::RT_ALE, 1, this->units[unitID].owner) diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index d2780815e..1848f7299 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -59507,7 +59507,7 @@ SHC_3BB0A8C1_0x0053A148 | 0.0% | Pending SHC_3BB0A8C1_0x0053A149 | 0.0% | Pending -SHC_3BB0A8C1_0x0053A150 | 31.6% | orig shares call tails +SHC_3BB0A8C1_0x0053A150 | 56.9% | reg alloc, spill order SHC_3BB0A8C1_0x0053A458 | 0.0% | Pending From 813807ae5ebae438790ca97b80d6658d58fe6f45 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 16:04:53 +0200 Subject: [PATCH 222/299] reimplement: SHC_3BB0A8C1_0x00536780 32.75% loop shape, reg alloc --- .../isTowerTileOvercrowdedByCurrentPlayer.cpp | 26 +++++++++---------- status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/isTowerTileOvercrowdedByCurrentPlayer.cpp b/src/OpenSHC/Map/Units/UnitsState/isTowerTileOvercrowdedByCurrentPlayer.cpp index 93e6eba71..ccae56692 100644 --- a/src/OpenSHC/Map/Units/UnitsState/isTowerTileOvercrowdedByCurrentPlayer.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/isTowerTileOvercrowdedByCurrentPlayer.cpp @@ -13,6 +13,7 @@ namespace Map { namespace Units { using OpenSHC::Map::Buildings::BuildingType; + using OpenSHC::Map::Buildings::BuildingTypeShort; using OpenSHC::WindowsHelper::Enums::BOOLEnum; // FUNCTION: STRONGHOLDCRUSADER 0x00536780 @@ -22,24 +23,21 @@ namespace Map { if (_buildingID == 0) { return FALSE; } - switch (DAT_BuildingsState::instance.buildings[_buildingID].buildingType) { - 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: - case OpenSHC::Map::Buildings::BT_STONEKEEP: - case OpenSHC::Map::Buildings::BT_STRONGHOLD: - case OpenSHC::Map::Buildings::BT_KEEPFOUR: - case OpenSHC::Map::Buildings::BT_KEEPFIVE: - break; - default: + BuildingTypeShort _buildingType = DAT_BuildingsState::instance.buildings[_buildingID].buildingType; + if (_buildingType != OpenSHC::Map::Buildings::BT_TOWER1 + && _buildingType != OpenSHC::Map::Buildings::BT_TOWER2 + && _buildingType != OpenSHC::Map::Buildings::BT_TOWER3 + && _buildingType != OpenSHC::Map::Buildings::BT_TOWER4 + && _buildingType != OpenSHC::Map::Buildings::BT_TOWER5 + && _buildingType != OpenSHC::Map::Buildings::BT_STONEKEEP + && _buildingType != OpenSHC::Map::Buildings::BT_STRONGHOLD + && _buildingType != OpenSHC::Map::Buildings::BT_KEEPFOUR + && _buildingType != OpenSHC::Map::Buildings::BT_KEEPFIVE) { return FALSE; } int _tileCapacity = DAT_BuildingsState::instance.buildings[_buildingID].widthOrHeight * DAT_BuildingsState::instance.buildings[_buildingID].widthOrHeight; - if (DAT_BuildingsState::instance.buildings[_buildingID].buildingType - == OpenSHC::Map::Buildings::BT_TOWER1) { + if (_buildingType == OpenSHC::Map::Buildings::BT_TOWER1) { _tileCapacity = 5; } int _ownUnitsOnBuilding = 0; diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 1848f7299..6ca0c506c 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -51143,7 +51143,7 @@ SHC_3BB0A8C1_0x00536690 | 92.1% | Style pass, asm differs SHC_3BB0A8C1_0x00536710 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x00536780 | 20.5% | orig unrolls counter loop x3 +SHC_3BB0A8C1_0x00536780 | 32.8% | loop shape, reg alloc SHC_3BB0A8C1_0x00536860 | 0.0% | Pending From 3be58a5402b79dd2a9b33ce67d7047286ce5809f Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 16:06:46 +0200 Subject: [PATCH 223/299] reimplement: SHC_3BB0A8C1_0x0053D9C0 25.82% reg alloc, hoisted loads --- src/OpenSHC/Map/Units/UnitsState/getUnitInHitBox.cpp | 4 ++-- status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/getUnitInHitBox.cpp b/src/OpenSHC/Map/Units/UnitsState/getUnitInHitBox.cpp index 5bcc93073..d31a3fe99 100644 --- a/src/OpenSHC/Map/Units/UnitsState/getUnitInHitBox.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/getUnitInHitBox.cpp @@ -23,7 +23,7 @@ namespace Map { { int _hitboxXStart; int _hitboxXEnd; - if (DAT_MouseState::instance.hitboxXEnd < DAT_MouseState::instance.hitboxXStart) { + if ((int)DAT_MouseState::instance.hitboxXStart > (int)DAT_MouseState::instance.hitboxXEnd) { _hitboxXStart = DAT_MouseState::instance.hitboxXEnd; _hitboxXEnd = DAT_MouseState::instance.hitboxXStart; } else { @@ -32,7 +32,7 @@ namespace Map { } int _hitboxYStart; int _hitboxYEnd; - if (DAT_MouseState::instance.hitboxYEnd < DAT_MouseState::instance.hitboxYStart) { + if ((int)DAT_MouseState::instance.hitboxYStart > (int)DAT_MouseState::instance.hitboxYEnd) { _hitboxYStart = DAT_MouseState::instance.hitboxYEnd; _hitboxYEnd = DAT_MouseState::instance.hitboxYStart; } else { diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 6ca0c506c..2b7d44451 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -60019,7 +60019,7 @@ SHC_3BB0A8C1_0x0053D850 | 69.8% | reg alloc differs SHC_3BB0A8C1_0x0053D900 | 68.8% | orig caches x/y in locals -SHC_3BB0A8C1_0x0053D9C0 | 19.2% | orig shares branch tails +SHC_3BB0A8C1_0x0053D9C0 | 25.8% | reg alloc, hoisted loads SHC_3BB0A8C1_0x0053DC9C | 0.0% | Pending From 76517f251ffb3a777b2713e4da56301a98336628 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 16:07:55 +0200 Subject: [PATCH 224/299] reimplement: SHC_3BB0A8C1_0x0053D3D0 28.17% reg alloc, spill order --- src/OpenSHC/Map/Units/UnitsState/setDestinationForUnit.cpp | 4 ++-- status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/setDestinationForUnit.cpp b/src/OpenSHC/Map/Units/UnitsState/setDestinationForUnit.cpp index 9ec6f01c2..5654c9353 100644 --- a/src/OpenSHC/Map/Units/UnitsState/setDestinationForUnit.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/setDestinationForUnit.cpp @@ -21,8 +21,8 @@ namespace Map { /* check by unit type */ int _ableToClimbTowers = DAT_UnitPropertiesDefinedData::instance.ABLE_TO_CLIMB_TOWERS[(short)this->units[unitID].unitType]; - /* the 400x400 map of placeable tiles at 0x021AEC98 */ - if (x > 399 || y > 399 || *(char*)(y * 400 + 0x21aec98 + x) == '\0') { + if (x > 399 || y > 399 + || DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[y * 400 + x] == 0) { DAT_PathFindingState::instance.allAssassinsUnk = 0; return FALSE; } diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 2b7d44451..7c57d3680 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -60013,7 +60013,7 @@ SHC_3BB0A8C1_0x0053D3C1 | 0.0% | Pending SHC_3BB0A8C1_0x0053D3C2 | 0.0% | Pending -SHC_3BB0A8C1_0x0053D3D0 | 21.5% | orig dups climb resolve +SHC_3BB0A8C1_0x0053D3D0 | 28.2% | reg alloc, spill order SHC_3BB0A8C1_0x0053D850 | 69.8% | reg alloc differs From 6c6075e05871f5fa677ca0faff9a5bf20db24b2b Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 16:09:09 +0200 Subject: [PATCH 225/299] reimplement: SHC_3BB0A8C1_0x00537AA0 40.00% reg alloc --- .../Map/Units/UnitsState/findClosestAnimalStoreResult.cpp | 3 +-- status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/findClosestAnimalStoreResult.cpp b/src/OpenSHC/Map/Units/UnitsState/findClosestAnimalStoreResult.cpp index 7b3ab6d8e..8767098d6 100644 --- a/src/OpenSHC/Map/Units/UnitsState/findClosestAnimalStoreResult.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/findClosestAnimalStoreResult.cpp @@ -24,8 +24,7 @@ namespace Map { if (x > 399 || y > 399) { return 0; } - /* the 400x400 map of placeable tiles at 0x021AEC98 */ - if (*(char*)(y * 400 + 0x21aec98 + x) == '\0') { + if (DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[y * 400 + x] == 0) { return 0; } ushort _areaOfOrigin diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 7c57d3680..e2082adcb 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -51249,7 +51249,7 @@ SHC_3BB0A8C1_0x005378F0 | 0.0% | Pending SHC_3BB0A8C1_0x00537A00 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x00537AA0 | 38.9% | orig walks unit ptr +SHC_3BB0A8C1_0x00537AA0 | 40.0% | reg alloc SHC_3BB0A8C1_0x00537B20 | 0.0% | Pending From 2681ed4de41a0f7789a35e34647cca803030d01e Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 16:09:10 +0200 Subject: [PATCH 226/299] reimplement: SHC_3BB0A8C1_0x00537C10 50.89% reg alloc --- .../Map/Units/UnitsState/findClosestEnemyByAreaAndRange.cpp | 2 +- status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/findClosestEnemyByAreaAndRange.cpp b/src/OpenSHC/Map/Units/UnitsState/findClosestEnemyByAreaAndRange.cpp index 4fa119665..d8ce6bf93 100644 --- a/src/OpenSHC/Map/Units/UnitsState/findClosestEnemyByAreaAndRange.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/findClosestEnemyByAreaAndRange.cpp @@ -21,7 +21,7 @@ namespace Map { if (x >= 400 || y >= 400) { return 0; } - if (*(char*)(y * 400 + 0x21aec98 + x) == '\0') { + if (DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[y * 400 + x] == 0) { return 0; } ushort _areaOfOrigin diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index e2082adcb..849b2b6ec 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -51253,7 +51253,7 @@ SHC_3BB0A8C1_0x00537AA0 | 40.0% | reg alloc SHC_3BB0A8C1_0x00537B20 | 0.0% | Pending -SHC_3BB0A8C1_0x00537C10 | 48.5% | orig walks unit ptr +SHC_3BB0A8C1_0x00537C10 | 50.9% | reg alloc SHC_3BB0A8C1_0x00537C90 | 0.0% | Pending From 4536e95c523ae7b73ae6451af801e87918c7c949 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 16:09:10 +0200 Subject: [PATCH 227/299] reimplement: SHC_3BB0A8C1_0x005371F0 38.54% reg alloc, loop shape --- .../Map/Units/UnitsState/findFreeTileNearby.cpp | 12 ++++-------- status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/findFreeTileNearby.cpp b/src/OpenSHC/Map/Units/UnitsState/findFreeTileNearby.cpp index 14d01b5a1..63a48e2da 100644 --- a/src/OpenSHC/Map/Units/UnitsState/findFreeTileNearby.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/findFreeTileNearby.cpp @@ -96,8 +96,7 @@ namespace Map { if (_checkX >= 400 || _checkY >= 400) { continue; } - /* the 400x400 map of placeable tiles at 0x021AEC98 */ - if (*(char*)(_checkX + 0x21aec98 + _checkY * 400) == '\0') { + if (DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[_checkX + _checkY * 400] == 0) { continue; } int _checkTile = DAT_ViewportRenderState::instance.translationMatrix[_checkY].addXgetTile @@ -121,8 +120,7 @@ namespace Map { if (_checkX >= 400 || _checkY >= 400) { continue; } - /* the 400x400 map of placeable tiles at 0x021AEC98 */ - if (*(char*)(_checkX + 0x21aec98 + _checkY * 400) == '\0') { + if (DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[_checkX + _checkY * 400] == 0) { continue; } int _checkTile = DAT_ViewportRenderState::instance.translationMatrix[_checkY].addXgetTile @@ -146,8 +144,7 @@ namespace Map { if (_checkX >= 400 || _checkY >= 400) { continue; } - /* the 400x400 map of placeable tiles at 0x021AEC98 */ - if (*(char*)(_checkX + 0x21aec98 + _checkY * 400) == '\0') { + if (DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[_checkX + _checkY * 400] == 0) { continue; } int _checkTile = DAT_ViewportRenderState::instance.translationMatrix[_checkY].addXgetTile @@ -171,8 +168,7 @@ namespace Map { if (_checkX >= 400 || _checkY >= 400) { continue; } - /* the 400x400 map of placeable tiles at 0x021AEC98 */ - if (*(char*)(_checkX + 0x21aec98 + _checkY * 400) == '\0') { + if (DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[_checkX + _checkY * 400] == 0) { continue; } int _checkTile = DAT_ViewportRenderState::instance.translationMatrix[_checkY].addXgetTile diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 849b2b6ec..2fb8f80b8 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -51233,7 +51233,7 @@ SHC_3BB0A8C1_0x005371A0 | 35.7% | param store order differs SHC_3BB0A8C1_0x005371E0 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x005371F0 | 36.2% | orig walks XYPair ptrs +SHC_3BB0A8C1_0x005371F0 | 38.5% | reg alloc, loop shape SHC_3BB0A8C1_0x00537700 | 21.1% | loop shape, spills From 1556aa11fc97e332a68514c35a5ae44a7d4b38b5 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 16:09:11 +0200 Subject: [PATCH 228/299] reimplement: SHC_3BB0A8C1_0x0053E900 87.04% reg alloc --- src/OpenSHC/Map/Units/UnitsState/setPositionOfUnit.cpp | 3 +-- status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/setPositionOfUnit.cpp b/src/OpenSHC/Map/Units/UnitsState/setPositionOfUnit.cpp index 1c52ff938..8a293c1c0 100644 --- a/src/OpenSHC/Map/Units/UnitsState/setPositionOfUnit.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/setPositionOfUnit.cpp @@ -12,8 +12,7 @@ namespace Map { if (x >= 400 || y >= 400) { return; } - /* the 400x400 map of placeable tiles at 0x021AEC98 */ - if (*(char*)(y * 400 + 0x21aec98 + x) == '\0') { + if (DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[y * 400 + x] == 0) { return; } this->units[unitID].currentIndexInPathPlan = 0; diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 2fb8f80b8..ea64fd2ec 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -60097,7 +60097,7 @@ SHC_3BB0A8C1_0x0053E870 | 85.7% | reg alloc differs SHC_3BB0A8C1_0x0053E8D0 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x0053E900 | 87.0% | reg alloc differs +SHC_3BB0A8C1_0x0053E900 | 87.0% | reg alloc SHC_3BB0A8C1_0x0053E9F0 | 56.8% | orig caches x/y in locals From 165e1cf35a37ee54a13691b69b566e940a8d8891 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 19:51:52 +0200 Subject: [PATCH 229/299] reimplement: SHC_3BB0A8C1_0x0054B0D0 39.18% 2-reg addressing, reg alloc --- .../Units/UnitsState/acquireShootTarget.cpp | 108 +++++++++--------- status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 54 insertions(+), 56 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/acquireShootTarget.cpp b/src/OpenSHC/Map/Units/UnitsState/acquireShootTarget.cpp index 2729861fb..62df6c1e5 100644 --- a/src/OpenSHC/Map/Units/UnitsState/acquireShootTarget.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/acquireShootTarget.cpp @@ -30,7 +30,6 @@ namespace Map { BOOLEnum UnitsState::acquireShootTarget(int unitID) { - short* psVar1; UnitTypeShort UVar4; short sVar5; int _unitTotalHeight; @@ -48,10 +47,6 @@ namespace Map { int local_10; int local_c; int local_8; - short _unitID_2; - int _unitID; - - _unitID = unitID; int _unitPlayerID = (int)this->units[unitID].owner; int _microXUnit = (int)this->units[unitID].microXPosition; int _microYUnit = (int)this->units[unitID].microYPosition; @@ -168,52 +163,56 @@ namespace Map { | OpenSHC::Map::Units::States::US_IDLEUnk))))) && (DAT_GameState::instance.mapAndTime.playerTeams[this->units[_0x04_targetUnitID].owner] != DAT_GameState::instance.mapAndTime.playerTeams[_unitPlayerID])) { - psVar1 = &this->units[_0x04_targetUnitID].microYPosition; - short* psVar2 = &this->units[_0x04_targetUnitID].microXPosition; _0x04_yDifference = ((int)(_microYUnit + (_microYUnit >> 0x1f & 7U)) >> 3) - - ((int)((int)*psVar1 + ((int)*psVar1 >> 0x1f & 7U)) >> 3); + - ((int)((int)this->units[_0x04_targetUnitID].microYPosition + + ((int)this->units[_0x04_targetUnitID].microYPosition >> 0x1f & 7U)) + >> 3); _xDifferenceToTarget = ((int)(_microXUnit + (_microXUnit >> 0x1f & 7U)) >> 3) - - ((int)((int)*psVar2 + ((int)*psVar2 >> 0x1f & 7U)) >> 3); + - ((int)((int)this->units[_0x04_targetUnitID].microXPosition + + ((int)this->units[_0x04_targetUnitID].microXPosition >> 0x1f & 7U)) + >> 3); if (_xDifferenceToTarget * _xDifferenceToTarget + _0x04_yDifference * _0x04_yDifference <= _rangeSquared) { - short* psVar3 = &this->units[_0x04_targetUnitID].terrainOrClimbHeight; - _unitID = MACRO_CALL_MEMBER(OpenSHC::Map::Entities::EntityState_Func::arrowShootingRelated, - DAT_EntityState::ptr)(_microXUnit, _microYUnit, _unitTotalHeight + 0x1e, - (int)((int)(*psVar2)), (int)((int)(*psVar1)), - (int)((int)(this->units[_0x04_targetUnitID].buildingHeight + 0x1a - + this->units[_0x04_targetUnitID].terrainOrClimbHeight))); - if (((_unitID <= 0) + int _shootDistanceScore + = MACRO_CALL_MEMBER(OpenSHC::Map::Entities::EntityState_Func::arrowShootingRelated, + DAT_EntityState::ptr)(_microXUnit, _microYUnit, _unitTotalHeight + 0x1e, + (int)((int)(this->units[_0x04_targetUnitID].microXPosition)), + (int)((int)(this->units[_0x04_targetUnitID].microYPosition)), + (int)((int)(this->units[_0x04_targetUnitID].buildingHeight + 0x1a + + this->units[_0x04_targetUnitID].terrainOrClimbHeight))); + if (((_shootDistanceScore <= 0) || (UVar4 = this->units[unitID].unitType, UVar4 == OpenSHC::Map::Units::UT_S_MANGONEL)) || (UVar4 == OpenSHC::Map::Units::UT_S_BALLISTA)) { if (this->units[unitID].unitType == OpenSHC::Map::Units::UT_HUNTER) { return FALSE; } this->units[unitID].shootTargetedUnit = -2; - this->units[unitID].shootTargetMicroX = *psVar2; - this->units[unitID].shootTargetMicroY = *psVar1; - this->units[unitID].shootTargetZ = *psVar3; + this->units[unitID].shootTargetMicroX = this->units[_0x04_targetUnitID].microXPosition; + this->units[unitID].shootTargetMicroY = this->units[_0x04_targetUnitID].microYPosition; + this->units[unitID].shootTargetZ = this->units[_0x04_targetUnitID].terrainOrClimbHeight; return TRUE; } this->units[unitID].shootTargetedUnit = sVar9; this->units[unitID].targetUID = this->units[_0x04_targetUnitID].uid; - this->units[unitID].distanceToEnemyUnitLadders = (short)_unitID; - this->units[unitID].shootTargetMicroX = *psVar2; - this->units[unitID].shootTargetMicroY = *psVar1; - this->units[unitID].shootTargetZ = *psVar3; - if (100 < _unitID) { + this->units[unitID].distanceToEnemyUnitLadders = (short)_shootDistanceScore; + this->units[unitID].shootTargetMicroX = this->units[_0x04_targetUnitID].microXPosition; + this->units[unitID].shootTargetMicroY = this->units[_0x04_targetUnitID].microYPosition; + this->units[unitID].shootTargetZ = this->units[_0x04_targetUnitID].terrainOrClimbHeight; + if (100 < _shootDistanceScore) { this->units[unitID].jugglerCount = 0; this->units[_0x04_targetUnitID].field233_0x39a = 1; return TRUE; } - _unitID = (int)*psVar3 + (int)this->units[_0x04_targetUnitID].buildingHeight; + int _targetTotalHeight = (int)this->units[_0x04_targetUnitID].terrainOrClimbHeight + + (int)this->units[_0x04_targetUnitID].buildingHeight; _unitPlayerID = (int)this->units[unitID].buildingHeight + (int)this->units[unitID].terrainOrClimbHeight; - if (_unitID + 0x46 < _unitPlayerID) { + if (_targetTotalHeight + 0x46 < _unitPlayerID) { this->units[unitID].jugglerCount = 1; this->units[_0x04_targetUnitID].field233_0x39a = 1; return TRUE; } - this->units[unitID].jugglerCount = (_unitID + -0x46 <= _unitPlayerID) - 1; + this->units[unitID].jugglerCount = (_targetTotalHeight + -0x46 <= _unitPlayerID) - 1; this->units[_0x04_targetUnitID].field233_0x39a = 1; return TRUE; } @@ -250,14 +249,15 @@ namespace Map { */ sVar9 = this->units[unitID].targetID_OR_targetBuildingID; + int _brazierEntityID; if ((DAT_TileMapState::instance.pitchDitches[sVar9].uid == this->units[unitID] .targetedUnitUIDUnk_OR_someAppearTileUnk_OR_buildingUID_OR_pitchDitchUID_OR_entityUID) - && (_unitID = MACRO_CALL_MEMBER(OpenSHC::Map::Entities::EntityState_Func::isBrazierNearby, + && (_brazierEntityID = MACRO_CALL_MEMBER(OpenSHC::Map::Entities::EntityState_Func::isBrazierNearby, DAT_EntityState::ptr)((int)this->units[unitID].x, (int)((int)(this->units[unitID].y)), (int)(( int)(this->units[unitID].buildingHeight + this->units[unitID].terrainOrClimbHeight))), - _unitID != 0)) { + _brazierEntityID != 0)) { this->units[unitID].shootTargetMicroX = DAT_TileMapState::instance.pitchDitches[sVar9].x * 8 + 4; this->units[unitID].shootTargetMicroY = DAT_TileMapState::instance.pitchDitches[sVar9].y * 8 + 4; this->units[unitID].shootTargetZ @@ -313,7 +313,7 @@ namespace Map { continue; switch (this->units[_enemy].unitType) { case OpenSHC::Map::Units::UT_ANTELOPESHDEER: - if (this->units[_unitID].unitType != OpenSHC::Map::Units::UT_HUNTER) + if (this->units[unitID].unitType != OpenSHC::Map::Units::UT_HUNTER) continue; break; case OpenSHC::Map::Units::UT_LIONSHWOLF: @@ -328,15 +328,15 @@ namespace Map { continue; break; case OpenSHC::Map::Units::UT_RABBIT: - _xDifferenceToTarget = (int)this->units[_unitID].tribeID; - if (((this->units[_unitID].unitType == OpenSHC::Map::Units::UT_HUNTER) + _xDifferenceToTarget = (int)this->units[unitID].tribeID; + if (((this->units[unitID].unitType == OpenSHC::Map::Units::UT_HUNTER) || (_xDifferenceToTarget <= 0)) || (DAT_TribesState::instance.tribes[_xDifferenceToTarget].field71_0x212 == 0)) continue; break; case OpenSHC::Map::Units::UT_CAGEDOG: if (DAT_GameState::instance.mapAndTime.playerTeams[this->units[_enemy].displayColorPlayerID] - == DAT_GameState::instance.mapAndTime.playerTeams[this->units[_unitID].owner]) + == DAT_GameState::instance.mapAndTime.playerTeams[this->units[unitID].owner]) continue; break; case OpenSHC::Map::Units::UT_A_ASSASSIN: @@ -382,8 +382,7 @@ namespace Map { case OpenSHC::Map::Units::UT_S_FBALLISTA: break; default: - if (DAT_GameSynchronyState::instance - .currentPlayerFullIDArray[this->units[_unitID].owner] + if (DAT_GameSynchronyState::instance.currentPlayerFullIDArray[this->units[unitID].owner] != -1) continue; if (this->units[_enemy].isSelectable_OR_matchTime == 0) { @@ -542,43 +541,42 @@ namespace Map { local_8 = local_c; } if (_entityType == 4) { - this->units[_unitID].shootTargetedUnit = -2; - this->units[_unitID].shootTargetMicroX = this->units[_validTargetID].microXPosition; - this->units[_unitID].shootTargetMicroY = this->units[_validTargetID].microYPosition; - this->units[_unitID].shootTargetZ = this->units[_validTargetID].terrainOrClimbHeight; + this->units[unitID].shootTargetedUnit = -2; + this->units[unitID].shootTargetMicroX = this->units[_validTargetID].microXPosition; + this->units[unitID].shootTargetMicroY = this->units[_validTargetID].microYPosition; + this->units[unitID].shootTargetZ = this->units[_validTargetID].terrainOrClimbHeight; return TRUE; } sVar9 = (short)_validTargetID; if ((_entityType == 0x25) || (_entityType == 0x14)) { - this->units[_unitID].shootTargetedUnit = sVar9; - this->units[_unitID].targetUID = this->units[_validTargetID].uid; - this->units[_unitID].distanceToEnemyUnitLadders = (short)local_8; - this->units[_unitID].shootTargetMicroX = this->units[_validTargetID].microXPosition; - this->units[_unitID].shootTargetMicroY = this->units[_validTargetID].microYPosition; - this->units[_unitID].shootTargetZ = this->units[_validTargetID].terrainOrClimbHeight; + this->units[unitID].shootTargetedUnit = sVar9; + this->units[unitID].targetUID = this->units[_validTargetID].uid; + this->units[unitID].distanceToEnemyUnitLadders = (short)local_8; + this->units[unitID].shootTargetMicroX = this->units[_validTargetID].microXPosition; + this->units[unitID].shootTargetMicroY = this->units[_validTargetID].microYPosition; + this->units[unitID].shootTargetZ = this->units[_validTargetID].terrainOrClimbHeight; return TRUE; } - psVar1 = &this->units[_validTargetID].field265_0x3dc; - *psVar1 = *psVar1 + 1; - this->units[_unitID].shootTargetedUnit = sVar9; - this->units[_unitID].field266_0x3de = sVar9; - this->units[_unitID].targetUID = this->units[_validTargetID].uid; - this->units[_unitID].distanceToEnemyUnitLadders = (short)local_8; + this->units[_validTargetID].field265_0x3dc = this->units[_validTargetID].field265_0x3dc + 1; + this->units[unitID].shootTargetedUnit = sVar9; + this->units[unitID].field266_0x3de = sVar9; + this->units[unitID].targetUID = this->units[_validTargetID].uid; + this->units[unitID].distanceToEnemyUnitLadders = (short)local_8; if (100 < local_8) { - this->units[_unitID].jugglerCount = 0; + this->units[unitID].jugglerCount = 0; this->units[_validTargetID].field233_0x39a = 1; return TRUE; } _unitPlayerID = (int)this->units[_validTargetID].terrainOrClimbHeight + (int)this->units[_validTargetID].buildingHeight; _microXUnit - = (int)this->units[_unitID].buildingHeight + (int)this->units[_unitID].terrainOrClimbHeight; + = (int)this->units[unitID].buildingHeight + (int)this->units[unitID].terrainOrClimbHeight; if (_unitPlayerID + 0x46 < _microXUnit) { - this->units[_unitID].jugglerCount = 1; + this->units[unitID].jugglerCount = 1; this->units[_validTargetID].field233_0x39a = 1; return TRUE; } - this->units[_unitID].jugglerCount = (_unitPlayerID + -0x46 <= _microXUnit) - 1; + this->units[unitID].jugglerCount = (_unitPlayerID + -0x46 <= _microXUnit) - 1; this->units[_validTargetID].field233_0x39a = 1; return TRUE; } diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index ea64fd2ec..1aaec719c 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -61833,7 +61833,7 @@ SHC_3BB0A8C1_0x0054B0CB | 0.0% | Pending SHC_3BB0A8C1_0x0054B0CC | 0.0% | Pending -SHC_3BB0A8C1_0x0054B0D0 | 39.2% | score tail, reg alloc +SHC_3BB0A8C1_0x0054B0D0 | 39.2% | 2-reg addressing, reg alloc SHC_3BB0A8C1_0x0054BE04 | 0.0% | Pending From c4822fbef0508db688c439273486d35cf83c037d Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 19:59:29 +0200 Subject: [PATCH 230/299] reimplement: SHC_3BB0A8C1_0x0054B0D0 39.29% 2-reg addressing, reg alloc --- src/OpenSHC/Map/Units/UnitsState/acquireShootTarget.cpp | 6 ++++-- status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/acquireShootTarget.cpp b/src/OpenSHC/Map/Units/UnitsState/acquireShootTarget.cpp index 62df6c1e5..093e85fb3 100644 --- a/src/OpenSHC/Map/Units/UnitsState/acquireShootTarget.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/acquireShootTarget.cpp @@ -307,9 +307,11 @@ namespace Map { } for (int local_24 = 0; local_24 < DAT_GameState::instance.playerDataArray[_unitPlayerID].enemies; local_24 = local_24 + 1) { - int _enemy = (int)*(short*)(_unitPlayerID * 0x39f4 + 0x115caf8 + local_24 * 2); + int _enemy = DAT_GameState::instance.playerDataArray[_unitPlayerID].enemyIDArray[local_24]; if ((this->units[_enemy].dying != 0) - || (this->units[_enemy].uid != *(int*)(_unitPlayerID * 10000 + 0x11a66f0 + local_24 * 4))) + || (this->units[_enemy].uid + != DAT_GameState::instance.mapAndTime + .playerEnemenyUnitUIDShortList[_unitPlayerID][local_24])) continue; switch (this->units[_enemy].unitType) { case OpenSHC::Map::Units::UT_ANTELOPESHDEER: diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 1aaec719c..1588b2fe2 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -61833,7 +61833,7 @@ SHC_3BB0A8C1_0x0054B0CB | 0.0% | Pending SHC_3BB0A8C1_0x0054B0CC | 0.0% | Pending -SHC_3BB0A8C1_0x0054B0D0 | 39.2% | 2-reg addressing, reg alloc +SHC_3BB0A8C1_0x0054B0D0 | 39.3% | 2-reg addressing, reg alloc SHC_3BB0A8C1_0x0054BE04 | 0.0% | Pending From 9e4b846d34c4a82429c7c8972b84bbf6f0d04b2a Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 20:01:35 +0200 Subject: [PATCH 231/299] reimplement: SHC_3BB0A8C1_0x0052EDC0 62.12% reg alloc, edi save site --- src/OpenSHC/Map/Units/UnitsState/disbandUnit.cpp | 4 +++- status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/disbandUnit.cpp b/src/OpenSHC/Map/Units/UnitsState/disbandUnit.cpp index 6c191e957..18b00fe19 100644 --- a/src/OpenSHC/Map/Units/UnitsState/disbandUnit.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/disbandUnit.cpp @@ -43,7 +43,9 @@ namespace Map { DAT_BuildingsState::ptr)((UnitType)(short)_unitType, &_refund); DAT_GameState::instance.playerDataArray[DAT_GameSynchronyState::instance.currentPlayerSlotID] .startResources[0xf] += _refund; - return DAT_GameSynchronyState::instance.currentPlayerSlotID * 0x39f4 + 0x115c2a0; + return ( + int)&DAT_GameState::instance.playerDataArray[DAT_GameSynchronyState::instance.currentPlayerSlotID] + .startResources[0xf]; } BOOLEnum _hasCampground = MACRO_CALL_MEMBER(OpenSHC::Game::GameStateStructures_Func::playerHasACampground, DAT_GameState::ptr)(this->units[unitID].owner); diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 1588b2fe2..fa5c14c7f 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -49311,7 +49311,7 @@ SHC_3BB0A8C1_0x0052E960 | 87.9% | reg alloc SHC_3BB0A8C1_0x0052EC10 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x0052EDC0 | 48.5% | branch shape differs +SHC_3BB0A8C1_0x0052EDC0 | 62.1% | reg alloc, edi save site SHC_3BB0A8C1_0x0052EED0 | 80.0% | orig caches unitType local From cf99606ed165b66041a06ee7868d258974036c10 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 20:03:06 +0200 Subject: [PATCH 232/299] reimplement: SHC_3BB0A8C1_0x0054B0D0 39.29% Style pass, asm differs --- src/OpenSHC/Map/Units/UnitsState/acquireShootTarget.cpp | 7 ++++--- status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/acquireShootTarget.cpp b/src/OpenSHC/Map/Units/UnitsState/acquireShootTarget.cpp index 093e85fb3..ccce33723 100644 --- a/src/OpenSHC/Map/Units/UnitsState/acquireShootTarget.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/acquireShootTarget.cpp @@ -592,9 +592,10 @@ namespace Map { this->units[unitID].shootTargetMicroX = sVar5 * 8; this->units[unitID].shootTargetedUnit = -1; this->units[unitID].shootTargetMicroY = sVar9 * 8; - this->units[unitID].shootTargetZ = (ushort) - * (byte*)(DAT_ViewportRenderState::instance.translationMatrix[sVar9].addXgetTile + 0x1d32c38 - + (int)sVar5); + this->units[unitID].shootTargetZ + = (ushort)DAT_TileMapState::instance + .HeightLayer[DAT_ViewportRenderState::instance.translationMatrix[sVar9].addXgetTile + + (int)sVar5]; return TRUE; } } diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index fa5c14c7f..32c11b9c6 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -61833,7 +61833,7 @@ SHC_3BB0A8C1_0x0054B0CB | 0.0% | Pending SHC_3BB0A8C1_0x0054B0CC | 0.0% | Pending -SHC_3BB0A8C1_0x0054B0D0 | 39.3% | 2-reg addressing, reg alloc +SHC_3BB0A8C1_0x0054B0D0 | 39.3% | Style pass, asm differs SHC_3BB0A8C1_0x0054BE04 | 0.0% | Pending From 4f8443dcd36e0db40f88f3fb1d74bcd80f6e9d8b Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 20:03:07 +0200 Subject: [PATCH 233/299] reimplement: SHC_3BB0A8C1_0x0054C1C0 32.51% reg alloc --- src/OpenSHC/Map/Units/UnitsState/unitClimbing.cpp | 11 ++++++----- status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/unitClimbing.cpp b/src/OpenSHC/Map/Units/UnitsState/unitClimbing.cpp index 08cb2b53a..5dbe7852f 100644 --- a/src/OpenSHC/Map/Units/UnitsState/unitClimbing.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/unitClimbing.cpp @@ -2,6 +2,7 @@ #include "OpenSHC/Map/Units/States/UnitState.hpp" #include "OpenSHC/Globals/DAT_PathFindingState.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" #include "OpenSHC/Globals/DAT_UnitPropertiesDefinedData.hpp" #include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" @@ -74,11 +75,11 @@ namespace Map { /* Climbing down */ this->units[unitID].terrainOrClimbHeight = this->units[unitID].terrainOrClimbHeight + 0xf; } - if ((short)(ushort) - * (byte*)(DAT_ViewportRenderState::instance - .translationMatrix[this->units[unitID].mimicCurrentYPosition] - .addXgetTile - + 0x1d32c38 + this->units[unitID].mimicCurrentXPosition) + if ((short)(ushort)DAT_TileMapState::instance + .HeightLayer[DAT_ViewportRenderState::instance + .translationMatrix[this->units[unitID].mimicCurrentYPosition] + .addXgetTile + + this->units[unitID].mimicCurrentXPosition] < this->units[unitID].terrainOrClimbHeight) { *(undefined2*)&this->units[unitID].climbingState = 5; } diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 32c11b9c6..a9618bdc8 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -62503,7 +62503,7 @@ SHC_3BB0A8C1_0x0054BFB3 | 0.0% | Pending SHC_3BB0A8C1_0x0054BFC0 | 46.1% | branch shape differs -SHC_3BB0A8C1_0x0054C1C0 | 32.5% | branch shape differs +SHC_3BB0A8C1_0x0054C1C0 | 32.5% | reg alloc SHC_3BB0A8C1_0x0054C4F0 | 14.0% | orig walks matrix row ptr From ac9c6ea68c758bef00327453219169a300df6088 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 20:03:07 +0200 Subject: [PATCH 234/299] reimplement: SHC_3BB0A8C1_0x00579300 33.71% reg alloc, dup tails --- src/OpenSHC/Map/Units/UnitsState/updateUnits.cpp | 7 +++---- status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/updateUnits.cpp b/src/OpenSHC/Map/Units/UnitsState/updateUnits.cpp index 7eb330753..9f280177c 100644 --- a/src/OpenSHC/Map/Units/UnitsState/updateUnits.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/updateUnits.cpp @@ -164,10 +164,9 @@ namespace Map { uVar9 = (uint)this->units[_currentUnitID].targetX_2; MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::setPositionOfUnit, this)( _currentUnitID, uVar9, uVar12, - (undefined4)((int)((uint) - * (byte*)(DAT_ViewportRenderState::instance.translationMatrix[uVar12] - .addXgetTile - + 0x1d32c38 + uVar9)))); + (undefined4)((int)((uint)DAT_TileMapState::instance.HeightLayer + [DAT_ViewportRenderState::instance.translationMatrix[uVar12].addXgetTile + + uVar9]))); this->units[DAT_CurrentUnitSlotID::instance].state.generic = OpenSHC::Map::Units::States::US_IDLEUnk; this->units[DAT_CurrentUnitSlotID::instance].destinationNeeded diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index a9618bdc8..24bd2d81a 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -66991,7 +66991,7 @@ SHC_3BB0A8C1_0x005792F8 | 0.0% | Pending SHC_3BB0A8C1_0x005792FC | 0.0% | Pending -SHC_3BB0A8C1_0x00579300 | 33.7% | Style pass, asm differs +SHC_3BB0A8C1_0x00579300 | 33.7% | reg alloc, dup tails SHC_3BB0A8C1_0x00579380 | 0.0% | Pending From 6564181e3167e922037145eccfe650a68e3b7be1 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 20:14:24 +0200 Subject: [PATCH 235/299] reimplement: SHC_3BB0A8C1_0x0054B0D0 39.29% 2-reg addressing, reg alloc --- .../Units/UnitsState/acquireShootTarget.cpp | 37 +++++++------------ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 14 insertions(+), 25 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/acquireShootTarget.cpp b/src/OpenSHC/Map/Units/UnitsState/acquireShootTarget.cpp index ccce33723..b12eb038c 100644 --- a/src/OpenSHC/Map/Units/UnitsState/acquireShootTarget.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/acquireShootTarget.cpp @@ -31,32 +31,21 @@ namespace Map { { UnitTypeShort UVar4; - short sVar5; - int _unitTotalHeight; - int _rangeSquared; BOOLEnum BVar6; - int iVar7; short sVar9; int _xDifferenceToTarget; - int _0x04_yDifference; - int _yDifferenceToTarget; int _entityType; - int local_30; - int local_2c; - int _validTargetID; - int local_10; - int local_c; - int local_8; int _unitPlayerID = (int)this->units[unitID].owner; int _microXUnit = (int)this->units[unitID].microXPosition; int _microYUnit = (int)this->units[unitID].microYPosition; - _unitTotalHeight = (int)this->units[unitID].buildingHeight + (int)this->units[unitID].terrainOrClimbHeight; - _validTargetID = 0; - local_30 = 100000; - local_8 = 0; - local_2c = 100000; - local_10 = 0; - local_c = 0; + int _unitTotalHeight + = (int)this->units[unitID].buildingHeight + (int)this->units[unitID].terrainOrClimbHeight; + int _validTargetID = 0; + int local_30 = 100000; + int local_8 = 0; + int local_2c = 100000; + int local_10 = 0; + int local_c = 0; /* switch based on unit type */ @@ -135,7 +124,7 @@ namespace Map { _entityType = 0x25; } - _rangeSquared = DAT_EntityDefinedData::instance.EntityTypeArrayForProjectileRange[_entityType] + int _rangeSquared = DAT_EntityDefinedData::instance.EntityTypeArrayForProjectileRange[_entityType] * DAT_EntityDefinedData::instance.EntityTypeArrayForProjectileRange[_entityType]; /* fetch attacking explicitness @@ -163,7 +152,7 @@ namespace Map { | OpenSHC::Map::Units::States::US_IDLEUnk))))) && (DAT_GameState::instance.mapAndTime.playerTeams[this->units[_0x04_targetUnitID].owner] != DAT_GameState::instance.mapAndTime.playerTeams[_unitPlayerID])) { - _0x04_yDifference = ((int)(_microYUnit + (_microYUnit >> 0x1f & 7U)) >> 3) + int _0x04_yDifference = ((int)(_microYUnit + (_microYUnit >> 0x1f & 7U)) >> 3) - ((int)((int)this->units[_0x04_targetUnitID].microYPosition + ((int)this->units[_0x04_targetUnitID].microYPosition >> 0x1f & 7U)) >> 3); @@ -346,8 +335,8 @@ namespace Map { continue; } _xDifferenceToTarget = (int)this->units[_enemy].microYPosition; - iVar7 = (int)this->units[_enemy].microXPosition; - _yDifferenceToTarget = ((int)(_microYUnit + (_microYUnit >> 0x1f & 7U)) >> 3) + int iVar7 = (int)this->units[_enemy].microXPosition; + int _yDifferenceToTarget = ((int)(_microYUnit + (_microYUnit >> 0x1f & 7U)) >> 3) - ((int)(_xDifferenceToTarget + (_xDifferenceToTarget >> 0x1f & 7U)) >> 3); _xDifferenceToTarget = ((int)(_microXUnit + (_microXUnit >> 0x1f & 7U)) >> 3) - ((int)(iVar7 + (iVar7 >> 0x1f & 7U)) >> 3); @@ -583,7 +572,7 @@ namespace Map { return TRUE; } sVar9 = this->units[unitID].attackAtTileY; - sVar5 = this->units[unitID].attackAtTileX; + short sVar5 = this->units[unitID].attackAtTileX; this->units[unitID].jugglerCount = -1; BVar6 = MACRO_CALL_MEMBER(OpenSHC::Rendering::ViewportRenderState_Func::xyAreValid, DAT_ViewportRenderState::ptr)((int)sVar5, (uint)((int)((int)sVar9))); diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 24bd2d81a..4b76c2f84 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -61833,7 +61833,7 @@ SHC_3BB0A8C1_0x0054B0CB | 0.0% | Pending SHC_3BB0A8C1_0x0054B0CC | 0.0% | Pending -SHC_3BB0A8C1_0x0054B0D0 | 39.3% | Style pass, asm differs +SHC_3BB0A8C1_0x0054B0D0 | 39.3% | 2-reg addressing, reg alloc SHC_3BB0A8C1_0x0054BE04 | 0.0% | Pending From 0cd5161c7c8975511438a69d9ee526eb1e66b0a5 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 20:15:17 +0200 Subject: [PATCH 236/299] reimplement: SHC_3BB0A8C1_0x00531920 25.58% extra spills, frame size --- .../UnitsState/processEntityDamageToUnit.cpp | 26 +++++++------------ 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/processEntityDamageToUnit.cpp b/src/OpenSHC/Map/Units/UnitsState/processEntityDamageToUnit.cpp index 0248cbb39..ee99deb88 100644 --- a/src/OpenSHC/Map/Units/UnitsState/processEntityDamageToUnit.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/processEntityDamageToUnit.cpp @@ -17,9 +17,9 @@ #include "OpenSHC/Globals/DAT_GameSynchronyState.hpp" #include "OpenSHC/Globals/DAT_SFXState.hpp" #include "OpenSHC/Globals/DAT_TileMapState.hpp" -#include "OpenSHC/Globals/DAT_UnitsState.hpp" #include "OpenSHC/Globals/DAT_TribesState.hpp" #include "OpenSHC/Globals/DAT_UnitPropertiesDefinedData.hpp" +#include "OpenSHC/Globals/DAT_UnitsState.hpp" namespace OpenSHC { namespace Map { @@ -37,19 +37,11 @@ namespace Map { BOOLEnum UnitsState::processEntityDamageToUnit(int unitID, int entityID, int tileDistance) { - short sVar3; - int bVar4; int _cowDiseaseDamage; uint uVar5; - int _entityShootingUnitID_2; int _unitHeight; - int _damage; eSFX sfxOffsetInArray; - int _siegeProjectile; - short _entityShootingUnitID; - EntityTypeShort _entityType; UnitTypeShort _entityType_2; - int _unitIsSiegeEngine; /* unclear what it does, but this function removes health from a unit, ranged @@ -57,19 +49,19 @@ namespace Map { */ int _unknown = (int)this->units[unitID].tribeID; - _unitIsSiegeEngine = 0; - _siegeProjectile = 0; - bVar4 = 0; + int _unitIsSiegeEngine = 0; + int _siegeProjectile = 0; + int bVar4 = 0; UnitTypeShort _unitType = this->units[unitID].unitType; - _entityShootingUnitID = DAT_EntityState::instance.entityArray[entityID].unitID_OR_seaGullID; - _entityShootingUnitID_2 = (int)_entityShootingUnitID; + short _entityShootingUnitID = DAT_EntityState::instance.entityArray[entityID].unitID_OR_seaGullID; + int _entityShootingUnitID_2 = (int)_entityShootingUnitID; if (unitID <= 0) { return FALSE; } if (_entityShootingUnitID_2 == unitID) { return FALSE; } - _entityType = DAT_EntityState::instance.entityArray[entityID].entityType; + EntityTypeShort _entityType = DAT_EntityState::instance.entityArray[entityID].entityType; if (_entityType == OpenSHC::Map::Entities::ET_FIRE) { return FALSE; } @@ -206,7 +198,7 @@ namespace Map { return FALSE; } int _unitAltitude = (int)this->units[unitID].terrainOrClimbHeight + (int)this->units[unitID].buildingHeight; - _damage = (int)DAT_EntityState::instance.entityArray[entityID].height; + int _damage = (int)DAT_EntityState::instance.entityArray[entityID].height; if (_damage < _unitAltitude) { return FALSE; } @@ -353,7 +345,7 @@ namespace Map { this->units[unitID].health = 0; } if (_entityShootingUnitID_2 != 0) { - sVar3 = this->units[unitID].field97_0xd0; + short sVar3 = this->units[unitID].field97_0xd0; if (sVar3 < 1000) { this->units[unitID].field97_0xd0 = sVar3 + 200; } From dc5db85671c59341c952a2c59a04af18b332b6cd Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 20:15:17 +0200 Subject: [PATCH 237/299] reimplement: SHC_3BB0A8C1_0x00549C70 29.20% mask reg alloc, frame ptr --- .../Map/Units/UnitsState/processMeleeInitiation.cpp | 9 +++------ status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/processMeleeInitiation.cpp b/src/OpenSHC/Map/Units/UnitsState/processMeleeInitiation.cpp index 607d656d9..236ba38bb 100644 --- a/src/OpenSHC/Map/Units/UnitsState/processMeleeInitiation.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/processMeleeInitiation.cpp @@ -29,9 +29,6 @@ namespace Map { { uint _neighbourHeights[8]; int _totalHeight; - int _playerID; - int _hasEnemyOnOwnTile; - uint _teamBitFlags; uint* _occupancyRow; int _adjacentTiles[24]; int _otherUnitID; @@ -67,13 +64,13 @@ namespace Map { == 0)))))))) { _totalHeight = (int)this->units[unitID].buildingHeight + (int)this->units[unitID].terrainOrClimbHeight; - _playerID = (int)this->units[unitID].owner; + int _playerID = (int)this->units[unitID].owner; DAT_TileMapState::instance.DAT_SomeTile = this->units[unitID].tile; DAT_TileMapState::instance.DAT_SomeY = (int)DAT_ViewportRenderState::instance .tileTranslationMatrix_YComponent[DAT_TileMapState::instance.DAT_SomeTile]; - _hasEnemyOnOwnTile = 0; - _teamBitFlags = MACRO_CALL_MEMBER( + int _hasEnemyOnOwnTile = 0; + uint _teamBitFlags = MACRO_CALL_MEMBER( OpenSHC::Game::GameStateStructures_Func::teamToBitFlagsUnk, DAT_GameState::ptr)(unitID); uint _enemyNeighbourFlags = 0; if ((*(uint*)((uchar*)DAT_TileMapState::instance.ptr_OccupancyLayer diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 4b76c2f84..2e38ec056 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -61405,7 +61405,7 @@ SHC_3BB0A8C1_0x00549B24 | 0.0% | Pending SHC_3BB0A8C1_0x00549B30 | 0.0% | Pending -SHC_3BB0A8C1_0x00549C70 | 29.2% | Style pass, asm differs +SHC_3BB0A8C1_0x00549C70 | 29.2% | mask reg alloc, frame ptr SHC_3BB0A8C1_0x0054A770 | 100.0% | Reimplemented From 035109f6f81d864a330b228603888636570ff2b9 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 20:32:06 +0200 Subject: [PATCH 238/299] reimplement: SHC_3BB0A8C1_0x0053A5B0 11.97% arg push hoist, y in reg --- .../UnitsState/renderDebugDataUnitData.cpp | 23 ++++++++++--------- status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/renderDebugDataUnitData.cpp b/src/OpenSHC/Map/Units/UnitsState/renderDebugDataUnitData.cpp index 4014d77ef..d1438375a 100644 --- a/src/OpenSHC/Map/Units/UnitsState/renderDebugDataUnitData.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/renderDebugDataUnitData.cpp @@ -36,10 +36,11 @@ namespace Map { MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( this->unitCount, _column0, _lineY, OpenSHC::Text::TTA_LEFT, 0x80ff, 0x12, TRUE, 0); MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( - (char*)s_Total_flies__005abdc0, x + 0x20, _lineY, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, TRUE, 0); - MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( - DAT_EntityState::instance.totalEntityCount, x + 0x20, _lineY, OpenSHC::Text::TTA_LEFT, 0x80ff, 0x12, + (char*)s_Total_flies__005abdc0, _column0 + 0x1e, _lineY, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, TRUE, 0); + MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( + DAT_EntityState::instance.totalEntityCount, _column0 + 0x1e, _lineY, OpenSHC::Text::TTA_LEFT, + 0x80ff, 0x12, TRUE, 0); _lineY = y + 0x1c; MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( (char*)s_No_of_teleports__005abdac, _column0, _lineY, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, @@ -48,11 +49,11 @@ namespace Map { DAT_PathFindingState::instance.numberOfClimbTeleports, _column0, _lineY, OpenSHC::Text::TTA_LEFT, 0x80ff, 0x12, TRUE, 0); MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( - (char*)s_greatest_loading__005abd98, x + 0x7a, _lineY, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, - FALSE, 0); + (char*)s_greatest_loading__005abd98, _column0 + 0x78, _lineY, OpenSHC::Text::TTA_LEFT, 0xffffff, + 0x12, FALSE, 0); MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( - DAT_PathFindingState::instance.debugGreatestClimbLoading, x + 0x7a, _lineY, OpenSHC::Text::TTA_LEFT, - 0x80ff, 0x12, TRUE, 0); + DAT_PathFindingState::instance.debugGreatestClimbLoading, _column0 + 0x78, _lineY, + OpenSHC::Text::TTA_LEFT, 0x80ff, 0x12, TRUE, 0); MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( (char*)s_total_zones__005abd88, _column0, y + 0x2a, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, FALSE, 0); @@ -69,18 +70,18 @@ namespace Map { (char*)s_Watching_chimp__005abd64, _column0, y, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, FALSE, 0); MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( _selectedUnitID, _column0, y, OpenSHC::Text::TTA_LEFT, 0x80ff, 0x12, TRUE, 0); - int _column1 = x + 0x20; + int _column1 = _column0 + 0x1e; MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( (char*)s_type__005abd5c, _column1, y, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, TRUE, 0); MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( (int)(short)this->units[_selectedUnitID].unitType, _column1, y, OpenSHC::Text::TTA_LEFT, 0x80ff, 0x12, TRUE, 0); - int _column2 = x + 0x3e; + int _column2 = _column0 + 0x3c; MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( (char*)s_player__005abd50, _column2, y, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, TRUE, 0); MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( _lineY, _column2, y, OpenSHC::Text::TTA_LEFT, 0x80ff, 0x12, TRUE, 0); - int _column3 = x + 0x5c; + int _column3 = _column0 + 0x5a; MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( (char*)s_status__005abd44, _column3, y, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, TRUE, 0); MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( @@ -106,7 +107,7 @@ namespace Map { MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( (int)this->units[_selectedUnitID].unitOrderWhenOnSameTile, _column3, y + 0xe, OpenSHC::Text::TTA_LEFT, 0x80ff, 0x12, TRUE, 0); - int _column4 = x + 0x7a; + int _column4 = _column0 + 0x78; MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( (char*)s_sloth__005abd04, _column4, y + 0xe, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, TRUE, 0); MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 2e38ec056..080277af7 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -59617,7 +59617,7 @@ SHC_3BB0A8C1_0x0053A4D0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0053A560 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x0053A5B0 | 11.4% | arg push scheduling +SHC_3BB0A8C1_0x0053A5B0 | 12.0% | arg push hoist, y in reg SHC_3BB0A8C1_0x0053B1F0 | 0.0% | Pending From 0cd562310a714be73995fd0900d388c9291db9a1 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 20:42:38 +0200 Subject: [PATCH 239/299] reimplement: SHC_3BB0A8C1_0x0053A5B0 25.73% arg push hoist, y cached --- src/OpenSHC/Map/Units/UnitsState/renderDebugDataUnitData.cpp | 2 +- status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/renderDebugDataUnitData.cpp b/src/OpenSHC/Map/Units/UnitsState/renderDebugDataUnitData.cpp index d1438375a..3260e0499 100644 --- a/src/OpenSHC/Map/Units/UnitsState/renderDebugDataUnitData.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/renderDebugDataUnitData.cpp @@ -80,7 +80,7 @@ namespace Map { MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( (char*)s_player__005abd50, _column2, y, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, TRUE, 0); MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( - _lineY, _column2, y, OpenSHC::Text::TTA_LEFT, 0x80ff, 0x12, TRUE, 0); + _ownerID, _column2, y, OpenSHC::Text::TTA_LEFT, 0x80ff, 0x12, TRUE, 0); int _column3 = _column0 + 0x5a; MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( (char*)s_status__005abd44, _column3, y, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, TRUE, 0); diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 080277af7..92b883363 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -59617,7 +59617,7 @@ SHC_3BB0A8C1_0x0053A4D0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0053A560 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x0053A5B0 | 12.0% | arg push hoist, y in reg +SHC_3BB0A8C1_0x0053A5B0 | 25.7% | arg push hoist, y cached SHC_3BB0A8C1_0x0053B1F0 | 0.0% | Pending From 201d7e5f9743746dbb5b785c6363ccf4630b27cb Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 21:30:21 +0200 Subject: [PATCH 240/299] reimplement: SHC_3BB0A8C1_0x0054B0D0 39.29% 2-reg addressing, reg alloc --- .../Units/UnitsState/acquireShootTarget.cpp | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/acquireShootTarget.cpp b/src/OpenSHC/Map/Units/UnitsState/acquireShootTarget.cpp index b12eb038c..20dd88e53 100644 --- a/src/OpenSHC/Map/Units/UnitsState/acquireShootTarget.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/acquireShootTarget.cpp @@ -165,10 +165,10 @@ namespace Map { int _shootDistanceScore = MACRO_CALL_MEMBER(OpenSHC::Map::Entities::EntityState_Func::arrowShootingRelated, DAT_EntityState::ptr)(_microXUnit, _microYUnit, _unitTotalHeight + 0x1e, - (int)((int)(this->units[_0x04_targetUnitID].microXPosition)), - (int)((int)(this->units[_0x04_targetUnitID].microYPosition)), - (int)((int)(this->units[_0x04_targetUnitID].buildingHeight + 0x1a - + this->units[_0x04_targetUnitID].terrainOrClimbHeight))); + (int)(this->units[_0x04_targetUnitID].microXPosition), + (int)(this->units[_0x04_targetUnitID].microYPosition), + (int)(this->units[_0x04_targetUnitID].buildingHeight + 0x1a + + this->units[_0x04_targetUnitID].terrainOrClimbHeight)); if (((_shootDistanceScore <= 0) || (UVar4 = this->units[unitID].unitType, UVar4 == OpenSHC::Map::Units::UT_S_MANGONEL)) || (UVar4 == OpenSHC::Map::Units::UT_S_BALLISTA)) { @@ -223,7 +223,7 @@ namespace Map { this->units[unitID].targetingType = OpenSHC::Map::Units::UIT_NO_INSTRUCTION_OR_MOVEUnk; if (sVar9 != 0) { MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::setDestinationForUnit, this)( - unitID, (uint)((int)((int)sVar9)), (uint)((int)((int)this->units[unitID]._someY_2)), 0); + unitID, (uint)(sVar9), (uint)((int)this->units[unitID]._someY_2), 0); this->units[unitID]._someX_2 = 0; this->units[unitID]._someY_2 = 0; this->units[unitID].moveDelay = 0; @@ -243,7 +243,7 @@ namespace Map { == this->units[unitID] .targetedUnitUIDUnk_OR_someAppearTileUnk_OR_buildingUID_OR_pitchDitchUID_OR_entityUID) && (_brazierEntityID = MACRO_CALL_MEMBER(OpenSHC::Map::Entities::EntityState_Func::isBrazierNearby, - DAT_EntityState::ptr)((int)this->units[unitID].x, (int)((int)(this->units[unitID].y)), + DAT_EntityState::ptr)((int)this->units[unitID].x, (int)(this->units[unitID].y), (int)(( int)(this->units[unitID].buildingHeight + this->units[unitID].terrainOrClimbHeight))), _brazierEntityID != 0)) { @@ -273,7 +273,7 @@ namespace Map { int _0x17_x = (int)this->units[unitID].attackAtTileX; int _0x17_tile = DAT_ViewportRenderState::instance.translationMatrix[_0x17_y].addXgetTile + _0x17_x; BVar6 = MACRO_CALL_MEMBER(OpenSHC::Rendering::ViewportRenderState_Func::xyAreValid, - DAT_ViewportRenderState::ptr)(_0x17_x, (uint)((int)(_0x17_y))); + DAT_ViewportRenderState::ptr)(_0x17_x, (uint)(_0x17_y)); if ((BVar6 != FALSE) && ((DAT_TileMapState::instance.LogicLayer[_0x17_tile] & 0x100U) != 0)) { this->units[unitID].shootTargetMicroX = this->units[unitID].attackAtTileX * 8; this->units[unitID].shootTargetMicroY = this->units[unitID].attackAtTileY * 8; @@ -507,9 +507,9 @@ namespace Map { && (iVar7 = MACRO_CALL_MEMBER(OpenSHC::Map::Entities::EntityState_Func::arrowShootingRelated, DAT_EntityState::ptr)(_microXUnit, _microYUnit, _unitTotalHeight + 0x1e, - (int)((int)(this->units[_enemy].microXPosition)), iVar7, - (int)((int)(this->units[_enemy].buildingHeight + 0x1a - + this->units[_enemy].terrainOrClimbHeight))), + (int)(this->units[_enemy].microXPosition), iVar7, + (int)(this->units[_enemy].buildingHeight + 0x1a + + this->units[_enemy].terrainOrClimbHeight)), 0 < iVar7)) { if (_xDifferenceToTarget < local_30) { local_30 = _xDifferenceToTarget; @@ -575,7 +575,7 @@ namespace Map { short sVar5 = this->units[unitID].attackAtTileX; this->units[unitID].jugglerCount = -1; BVar6 = MACRO_CALL_MEMBER(OpenSHC::Rendering::ViewportRenderState_Func::xyAreValid, - DAT_ViewportRenderState::ptr)((int)sVar5, (uint)((int)((int)sVar9))); + DAT_ViewportRenderState::ptr)((int)sVar5, (uint)(sVar9)); if (BVar6 != FALSE) { sVar5 = this->units[unitID].attackAtTileX; this->units[unitID].shootTargetMicroX = sVar5 * 8; From bc50400ab9e2f811767df65f298bd627b3baf69e Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 21:30:21 +0200 Subject: [PATCH 241/299] reimplement: SHC_3BB0A8C1_0x00531920 25.58% extra spills, frame size --- .../Map/Units/UnitsState/processEntityDamageToUnit.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/processEntityDamageToUnit.cpp b/src/OpenSHC/Map/Units/UnitsState/processEntityDamageToUnit.cpp index ee99deb88..c8fcc9621 100644 --- a/src/OpenSHC/Map/Units/UnitsState/processEntityDamageToUnit.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/processEntityDamageToUnit.cpp @@ -303,7 +303,7 @@ namespace Map { this->units[unitID].state.generic = OpenSHC::Map::Units::States::US_STONE_DEATH_01; this->units[unitID].tunnelerFinishedDigging = 1; MACRO_CALL_MEMBER(OpenSHC::Audio::SFX::SFXState_Func::playSFXAtLocation, DAT_SFXState::ptr)( - (int)_unitXPosition, (int)((int)(_unitYPosition)), OpenSHC::DE::SHCDE::FX_SPLAT); + (int)_unitXPosition, (int)(_unitYPosition), OpenSHC::DE::SHCDE::FX_SPLAT); this->units[unitID].health = 0; return TRUE; } @@ -321,7 +321,7 @@ namespace Map { _damage = DAT_UnitPropertiesDefinedData::instance.BOLT_DAMAGE[(short)this->units[unitID].unitType]; } _damage = MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::computeDamageFearFactorBonus, this)( - _damage, (int)((int)(DAT_EntityState::instance.entityArray[entityID].owner))); + _damage, (int)(DAT_EntityState::instance.entityArray[entityID].owner)); if (_unitIsSiegeEngine) { _damage = _damage / 2; } @@ -406,8 +406,7 @@ namespace Map { break; case OpenSHC::Map::Units::UT_S_TREBUCHET: MACRO_CALL_MEMBER(OpenSHC::Audio::SFX::SFXState_Func::playSFXAtLocation, DAT_SFXState::ptr)( - (int)this->units[unitID].x, (int)((int)(this->units[unitID].y)), - OpenSHC::DE::SHCDE::FX_TR_DIE); + (int)this->units[unitID].x, (int)(this->units[unitID].y), OpenSHC::DE::SHCDE::FX_TR_DIE); break; case OpenSHC::Map::Units::UT_S_SHIELD: if ((this->units[unitID].digTileX__OR__countCurrentlyManningEnginers__OR__forCowsRandomBelow300 From 41442ae46e9044ee5dc0c328649b2620ff12be08 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 21:30:22 +0200 Subject: [PATCH 242/299] reimplement: SHC_3BB0A8C1_0x0053A5B0 33.37% arg push hoist, y cached --- src/OpenSHC/Map/Units/UnitsState/renderDebugDataUnitData.cpp | 2 +- status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/renderDebugDataUnitData.cpp b/src/OpenSHC/Map/Units/UnitsState/renderDebugDataUnitData.cpp index 3260e0499..5cf4a85f0 100644 --- a/src/OpenSHC/Map/Units/UnitsState/renderDebugDataUnitData.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/renderDebugDataUnitData.cpp @@ -215,7 +215,7 @@ namespace Map { MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( *(int*)(this->units[_selectedUnitID].manningEngineerRef + this->units[_selectedUnitID].working * 2 + -0x16), - _column0, _lineY, OpenSHC::Text::TTA_LEFT, (uint)((int)(33023)), 0x12, TRUE, 0); + _column0, _lineY, OpenSHC::Text::TTA_LEFT, (uint)(33023), 0x12, TRUE, 0); MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderTextToScreen, DAT_TextManagerObject::ptr)( (char*)s_Av_005abc34, _column1, _lineY, OpenSHC::Text::TTA_LEFT, 0xffffff, 0x12, TRUE, 0); MACRO_CALL_MEMBER(OpenSHC::Text::TextManager_Func::renderNumberToScreen2, DAT_TextManagerObject::ptr)( diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 92b883363..bf086bf1c 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -59617,7 +59617,7 @@ SHC_3BB0A8C1_0x0053A4D0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x0053A560 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x0053A5B0 | 25.7% | arg push hoist, y cached +SHC_3BB0A8C1_0x0053A5B0 | 33.4% | arg push hoist, y cached SHC_3BB0A8C1_0x0053B1F0 | 0.0% | Pending From 6d977b4eb514b911cef23256c16c71fcd146647c Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 21:30:22 +0200 Subject: [PATCH 243/299] reimplement: SHC_3BB0A8C1_0x00579300 33.71% reg alloc, dup tails --- src/OpenSHC/Map/Units/UnitsState/updateUnits.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/updateUnits.cpp b/src/OpenSHC/Map/Units/UnitsState/updateUnits.cpp index 9f280177c..b0d24ca40 100644 --- a/src/OpenSHC/Map/Units/UnitsState/updateUnits.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/updateUnits.cpp @@ -153,7 +153,7 @@ namespace Map { if (this->units[_currentUnitID].unitType == OpenSHC::Map::Units::UT_CHICKEN) { MACRO_CALL_MEMBER(OpenSHC::Audio::SFX::SFXState_Func::playSFXAtLocation, DAT_SFXState::ptr)((int)this->units[_currentUnitID].x, - (int)((int)(this->units[_currentUnitID].y)), OpenSHC::DE::SHCDE::FX_CHICKEN_FLAP); + (int)(this->units[_currentUnitID].y), OpenSHC::DE::SHCDE::FX_CHICKEN_FLAP); _currentUnitID = DAT_CurrentUnitSlotID::instance; } if ((999 < (int)(DAT_GameCore::instance.mapTimeInTicks - this->units[_currentUnitID].time)) @@ -164,7 +164,7 @@ namespace Map { uVar9 = (uint)this->units[_currentUnitID].targetX_2; MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::setPositionOfUnit, this)( _currentUnitID, uVar9, uVar12, - (undefined4)((int)((uint)DAT_TileMapState::instance.HeightLayer + (undefined4)((int)(DAT_TileMapState::instance.HeightLayer [DAT_ViewportRenderState::instance.translationMatrix[uVar12].addXgetTile + uVar9]))); this->units[DAT_CurrentUnitSlotID::instance].state.generic @@ -672,7 +672,7 @@ namespace Map { } _troopValue = MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::processUnitMove, this)(DAT_CurrentUnitSlotID::instance, - (int)((int)(this->units[DAT_CurrentUnitSlotID::instance].stateBasedSpeed))); + (int)(this->units[DAT_CurrentUnitSlotID::instance].stateBasedSpeed)); if (_troopValue != 0) { if (((this->units[DAT_CurrentUnitSlotID::instance].state.generic == OpenSHC::Map::Units::States::US_MOVE_TO_DESTINATION) From 0e8d062681351aac8f38c7494072f2028b0f4b52 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 21:33:43 +0200 Subject: [PATCH 244/299] reimplement: SHC_3BB0A8C1_0x00549C70 29.20% mask reg alloc, frame ptr --- .../Map/Units/UnitsState/processMeleeInitiation.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/processMeleeInitiation.cpp b/src/OpenSHC/Map/Units/UnitsState/processMeleeInitiation.cpp index 236ba38bb..43bc0eb85 100644 --- a/src/OpenSHC/Map/Units/UnitsState/processMeleeInitiation.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/processMeleeInitiation.cpp @@ -32,12 +32,10 @@ namespace Map { uint* _occupancyRow; int _adjacentTiles[24]; int _otherUnitID; - if ((((this->units[unitID].someUnitStat2_meleeDamageUnk != 0) - && (this->units[unitID].unknownTestAgainst0_2 == 0)) - && (this->units[unitID].unknownMovementRelated_0x2d2 == 0)) - && (((this->units[unitID].logicalState == OpenSHC::Map::Units::ULS_NORMAL - && (this->units[unitID].dying == 0)) - && (this->units[unitID].moveRelatedFlag != 1)))) { + if (this->units[unitID].someUnitStat2_meleeDamageUnk != 0 && this->units[unitID].unknownTestAgainst0_2 == 0 + && this->units[unitID].unknownMovementRelated_0x2d2 == 0 + && this->units[unitID].logicalState == OpenSHC::Map::Units::ULS_NORMAL && this->units[unitID].dying == 0 + && this->units[unitID].moveRelatedFlag != 1) { int _distanceThreshold; if (this->units[unitID].stateBasedSpeed <= 0) { /* From 39d92192e9d7b95481b751b1363945b8d7716254 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 21:33:44 +0200 Subject: [PATCH 245/299] reimplement: SHC_3BB0A8C1_0x0054B0D0 39.29% 2-reg addressing, reg alloc --- .../Units/UnitsState/acquireShootTarget.cpp | 125 +++++++++--------- 1 file changed, 64 insertions(+), 61 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/acquireShootTarget.cpp b/src/OpenSHC/Map/Units/UnitsState/acquireShootTarget.cpp index 20dd88e53..2cd77bc5a 100644 --- a/src/OpenSHC/Map/Units/UnitsState/acquireShootTarget.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/acquireShootTarget.cpp @@ -138,75 +138,78 @@ namespace Map { sVar9 = this->units[unitID].targetedUnitID__OR__engineerMannedSiegeEngineRef; int _0x04_targetUnitID = (int)sVar9; - if (((((this->units[_0x04_targetUnitID].uid - == this->units[unitID] - .targetedUnitUIDUnk_OR_someAppearTileUnk_OR_buildingUID_OR_pitchDitchUID_OR_entityUID) - && (this->units[_0x04_targetUnitID].dying == 0)) - && (this->units[_0x04_targetUnitID].logicalState == OpenSHC::Map::Units::ULS_NORMAL)) - && ((BVar6 = MACRO_CALL_MEMBER( - OpenSHC::Map::Units::UnitsState_Func::checkIfCitizenUnitIsAliveBasedOnState, this)( - _0x04_targetUnitID), - BVar6 == FALSE - && (this->units[_0x04_targetUnitID].state.generic - != (OpenSHC::Map::Units::States::US_STONE_DEATH_03 - | OpenSHC::Map::Units::States::US_IDLEUnk))))) - && (DAT_GameState::instance.mapAndTime.playerTeams[this->units[_0x04_targetUnitID].owner] - != DAT_GameState::instance.mapAndTime.playerTeams[_unitPlayerID])) { - int _0x04_yDifference = ((int)(_microYUnit + (_microYUnit >> 0x1f & 7U)) >> 3) - - ((int)((int)this->units[_0x04_targetUnitID].microYPosition - + ((int)this->units[_0x04_targetUnitID].microYPosition >> 0x1f & 7U)) - >> 3); - _xDifferenceToTarget = ((int)(_microXUnit + (_microXUnit >> 0x1f & 7U)) >> 3) - - ((int)((int)this->units[_0x04_targetUnitID].microXPosition - + ((int)this->units[_0x04_targetUnitID].microXPosition >> 0x1f & 7U)) - >> 3); - if (_xDifferenceToTarget * _xDifferenceToTarget + _0x04_yDifference * _0x04_yDifference - <= _rangeSquared) { - int _shootDistanceScore - = MACRO_CALL_MEMBER(OpenSHC::Map::Entities::EntityState_Func::arrowShootingRelated, - DAT_EntityState::ptr)(_microXUnit, _microYUnit, _unitTotalHeight + 0x1e, - (int)(this->units[_0x04_targetUnitID].microXPosition), - (int)(this->units[_0x04_targetUnitID].microYPosition), - (int)(this->units[_0x04_targetUnitID].buildingHeight + 0x1a - + this->units[_0x04_targetUnitID].terrainOrClimbHeight)); - if (((_shootDistanceScore <= 0) - || (UVar4 = this->units[unitID].unitType, UVar4 == OpenSHC::Map::Units::UT_S_MANGONEL)) - || (UVar4 == OpenSHC::Map::Units::UT_S_BALLISTA)) { - if (this->units[unitID].unitType == OpenSHC::Map::Units::UT_HUNTER) { - return FALSE; + if (this->units[_0x04_targetUnitID].uid + == this->units[unitID] + .targetedUnitUIDUnk_OR_someAppearTileUnk_OR_buildingUID_OR_pitchDitchUID_OR_entityUID + && this->units[_0x04_targetUnitID].dying == 0 + && this->units[_0x04_targetUnitID].logicalState == OpenSHC::Map::Units::ULS_NORMAL) { + BVar6 + = MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::checkIfCitizenUnitIsAliveBasedOnState, + this)(_0x04_targetUnitID); + if (BVar6 == FALSE + && this->units[_0x04_targetUnitID].state.generic + != (OpenSHC::Map::Units::States::US_STONE_DEATH_03 + | OpenSHC::Map::Units::States::US_IDLEUnk) + && DAT_GameState::instance.mapAndTime.playerTeams[this->units[_0x04_targetUnitID].owner] + != DAT_GameState::instance.mapAndTime.playerTeams[_unitPlayerID]) { + int _0x04_yDifference = ((int)(_microYUnit + (_microYUnit >> 0x1f & 7U)) >> 3) + - ((int)((int)this->units[_0x04_targetUnitID].microYPosition + + ((int)this->units[_0x04_targetUnitID].microYPosition >> 0x1f & 7U)) + >> 3); + _xDifferenceToTarget = ((int)(_microXUnit + (_microXUnit >> 0x1f & 7U)) >> 3) + - ((int)((int)this->units[_0x04_targetUnitID].microXPosition + + ((int)this->units[_0x04_targetUnitID].microXPosition >> 0x1f & 7U)) + >> 3); + if (_xDifferenceToTarget * _xDifferenceToTarget + _0x04_yDifference * _0x04_yDifference + <= _rangeSquared) { + int _shootDistanceScore + = MACRO_CALL_MEMBER(OpenSHC::Map::Entities::EntityState_Func::arrowShootingRelated, + DAT_EntityState::ptr)(_microXUnit, _microYUnit, _unitTotalHeight + 0x1e, + (int)(this->units[_0x04_targetUnitID].microXPosition), + (int)(this->units[_0x04_targetUnitID].microYPosition), + (int)(this->units[_0x04_targetUnitID].buildingHeight + 0x1a + + this->units[_0x04_targetUnitID].terrainOrClimbHeight)); + if (((_shootDistanceScore <= 0) + || (UVar4 = this->units[unitID].unitType, + UVar4 == OpenSHC::Map::Units::UT_S_MANGONEL)) + || (UVar4 == OpenSHC::Map::Units::UT_S_BALLISTA)) { + if (this->units[unitID].unitType == OpenSHC::Map::Units::UT_HUNTER) { + return FALSE; + } + this->units[unitID].shootTargetedUnit = -2; + this->units[unitID].shootTargetMicroX = this->units[_0x04_targetUnitID].microXPosition; + this->units[unitID].shootTargetMicroY = this->units[_0x04_targetUnitID].microYPosition; + this->units[unitID].shootTargetZ = this->units[_0x04_targetUnitID].terrainOrClimbHeight; + return TRUE; } - this->units[unitID].shootTargetedUnit = -2; + this->units[unitID].shootTargetedUnit = sVar9; + this->units[unitID].targetUID = this->units[_0x04_targetUnitID].uid; + this->units[unitID].distanceToEnemyUnitLadders = (short)_shootDistanceScore; this->units[unitID].shootTargetMicroX = this->units[_0x04_targetUnitID].microXPosition; this->units[unitID].shootTargetMicroY = this->units[_0x04_targetUnitID].microYPosition; this->units[unitID].shootTargetZ = this->units[_0x04_targetUnitID].terrainOrClimbHeight; - return TRUE; - } - this->units[unitID].shootTargetedUnit = sVar9; - this->units[unitID].targetUID = this->units[_0x04_targetUnitID].uid; - this->units[unitID].distanceToEnemyUnitLadders = (short)_shootDistanceScore; - this->units[unitID].shootTargetMicroX = this->units[_0x04_targetUnitID].microXPosition; - this->units[unitID].shootTargetMicroY = this->units[_0x04_targetUnitID].microYPosition; - this->units[unitID].shootTargetZ = this->units[_0x04_targetUnitID].terrainOrClimbHeight; - if (100 < _shootDistanceScore) { - this->units[unitID].jugglerCount = 0; + if (100 < _shootDistanceScore) { + this->units[unitID].jugglerCount = 0; + this->units[_0x04_targetUnitID].field233_0x39a = 1; + return TRUE; + } + int _targetTotalHeight = (int)this->units[_0x04_targetUnitID].terrainOrClimbHeight + + (int)this->units[_0x04_targetUnitID].buildingHeight; + _unitPlayerID = (int)this->units[unitID].buildingHeight + + (int)this->units[unitID].terrainOrClimbHeight; + if (_targetTotalHeight + 0x46 < _unitPlayerID) { + this->units[unitID].jugglerCount = 1; + this->units[_0x04_targetUnitID].field233_0x39a = 1; + return TRUE; + } + this->units[unitID].jugglerCount = (_targetTotalHeight + -0x46 <= _unitPlayerID) - 1; this->units[_0x04_targetUnitID].field233_0x39a = 1; return TRUE; } - int _targetTotalHeight = (int)this->units[_0x04_targetUnitID].terrainOrClimbHeight - + (int)this->units[_0x04_targetUnitID].buildingHeight; - _unitPlayerID - = (int)this->units[unitID].buildingHeight + (int)this->units[unitID].terrainOrClimbHeight; - if (_targetTotalHeight + 0x46 < _unitPlayerID) { - this->units[unitID].jugglerCount = 1; - this->units[_0x04_targetUnitID].field233_0x39a = 1; - return TRUE; + if (DAT_GameSynchronyState::instance.currentPlayerFullIDArray[this->units[unitID].owner] + != -1) { + return FALSE; } - this->units[unitID].jugglerCount = (_targetTotalHeight + -0x46 <= _unitPlayerID) - 1; - this->units[_0x04_targetUnitID].field233_0x39a = 1; - return TRUE; - } - if (DAT_GameSynchronyState::instance.currentPlayerFullIDArray[this->units[unitID].owner] != -1) { - return FALSE; } } /* From 6b24cacb9b0d79462631f57eb79c6359febc0c83 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 21:35:14 +0200 Subject: [PATCH 246/299] reimplement: SHC_3BB0A8C1_0x00579300 34.14% reg alloc, dup tails --- .../Map/Units/UnitsState/updateUnits.cpp | 108 +++++++++--------- status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 58 insertions(+), 52 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/updateUnits.cpp b/src/OpenSHC/Map/Units/UnitsState/updateUnits.cpp index b0d24ca40..d031f4c93 100644 --- a/src/OpenSHC/Map/Units/UnitsState/updateUnits.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/updateUnits.cpp @@ -135,49 +135,53 @@ namespace Map { } if (_unitIDBased8value == _rngNumber8) { int _unitTile = this->units[_currentUnitID].tile; - if (((((DAT_TileMapState::instance.PathConnectionLayer[_unitTile] == 0) - && ((DAT_TileMapState::instance.LogicLayer[_unitTile] & 0x40000000U) == 0)) - && (this->units[_currentUnitID].moveRelatedFlag != 1)) - && ((_buildingID = DAT_TileMapState::instance.BuildingLayer[_unitTile], - _buildingID == 0 - || (((DAT_BuildingsState::instance.buildings[_buildingID].logicalState - == OpenSHC::Map::Buildings::BLS_NORMAL - && (_buildingType - = DAT_BuildingsState::instance.buildings[_buildingID].buildingType, - DAT_BuildingDefinedData::instance - .BuildingIsGateHouseArray[(short)_buildingType] - == 0)) - && (_buildingType != OpenSHC::Map::Buildings::BT_DRAWBRIDGE)))))) - && (this->units[_currentUnitID].state.generic - != OpenSHC::Map::Units::States::US_DISAPPEAR)) { - if (this->units[_currentUnitID].unitType == OpenSHC::Map::Units::UT_CHICKEN) { - MACRO_CALL_MEMBER(OpenSHC::Audio::SFX::SFXState_Func::playSFXAtLocation, - DAT_SFXState::ptr)((int)this->units[_currentUnitID].x, - (int)(this->units[_currentUnitID].y), OpenSHC::DE::SHCDE::FX_CHICKEN_FLAP); - _currentUnitID = DAT_CurrentUnitSlotID::instance; - } - if ((999 < (int)(DAT_GameCore::instance.mapTimeInTicks - this->units[_currentUnitID].time)) - && (_unitType = this->units[_currentUnitID].unitType, - _unitType != OpenSHC::Map::Units::UT_S_TOWER)) { - if (_unitType == OpenSHC::Map::Units::UT_LORD) { - uint uVar12 = (uint)this->units[_currentUnitID].targetY_2; - uVar9 = (uint)this->units[_currentUnitID].targetX_2; - MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::setPositionOfUnit, this)( - _currentUnitID, uVar9, uVar12, - (undefined4)((int)(DAT_TileMapState::instance.HeightLayer - [DAT_ViewportRenderState::instance.translationMatrix[uVar12].addXgetTile - + uVar9]))); - this->units[DAT_CurrentUnitSlotID::instance].state.generic - = OpenSHC::Map::Units::States::US_IDLEUnk; - this->units[DAT_CurrentUnitSlotID::instance].destinationNeeded - = OpenSHC::Map::Units::Pathfinding::DNE_DESTINATION_HAS_BEEN_SET; - _currentUnitID = DAT_CurrentUnitSlotID::instance; - } else { - this->units[_currentUnitID].state.generic - = OpenSHC::Map::Units::States::US_DISAPPEAR; - this->units[DAT_CurrentUnitSlotID::instance].updateTickTracker = 0; + if (DAT_TileMapState::instance.PathConnectionLayer[_unitTile] == 0 + && (DAT_TileMapState::instance.LogicLayer[_unitTile] & 0x40000000U) == 0 + && this->units[_currentUnitID].moveRelatedFlag != 1) { + _buildingID = DAT_TileMapState::instance.BuildingLayer[_unitTile]; + if ((_buildingID == 0 + || (DAT_BuildingsState::instance.buildings[_buildingID].logicalState + == OpenSHC::Map::Buildings::BLS_NORMAL + && (_buildingType + = DAT_BuildingsState::instance.buildings[_buildingID].buildingType, + DAT_BuildingDefinedData::instance + .BuildingIsGateHouseArray[(short)_buildingType] + == 0) + && _buildingType != OpenSHC::Map::Buildings::BT_DRAWBRIDGE)) + && this->units[_currentUnitID].state.generic + != OpenSHC::Map::Units::States::US_DISAPPEAR) { + if (this->units[_currentUnitID].unitType == OpenSHC::Map::Units::UT_CHICKEN) { + MACRO_CALL_MEMBER(OpenSHC::Audio::SFX::SFXState_Func::playSFXAtLocation, + DAT_SFXState::ptr)((int)this->units[_currentUnitID].x, + (int)(this->units[_currentUnitID].y), OpenSHC::DE::SHCDE::FX_CHICKEN_FLAP); _currentUnitID = DAT_CurrentUnitSlotID::instance; } + if ((999 < (int)(DAT_GameCore::instance.mapTimeInTicks + - this->units[_currentUnitID].time)) + && (_unitType = this->units[_currentUnitID].unitType, + _unitType != OpenSHC::Map::Units::UT_S_TOWER)) { + if (_unitType == OpenSHC::Map::Units::UT_LORD) { + uint uVar12 = (uint)this->units[_currentUnitID].targetY_2; + uVar9 = (uint)this->units[_currentUnitID].targetX_2; + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::setPositionOfUnit, + this)(_currentUnitID, uVar9, uVar12, + (undefined4)((int)(DAT_TileMapState::instance + .HeightLayer[DAT_ViewportRenderState::instance + .translationMatrix[uVar12] + .addXgetTile + + uVar9]))); + this->units[DAT_CurrentUnitSlotID::instance].state.generic + = OpenSHC::Map::Units::States::US_IDLEUnk; + this->units[DAT_CurrentUnitSlotID::instance].destinationNeeded + = OpenSHC::Map::Units::Pathfinding::DNE_DESTINATION_HAS_BEEN_SET; + _currentUnitID = DAT_CurrentUnitSlotID::instance; + } else { + this->units[_currentUnitID].state.generic + = OpenSHC::Map::Units::States::US_DISAPPEAR; + this->units[DAT_CurrentUnitSlotID::instance].updateTickTracker = 0; + _currentUnitID = DAT_CurrentUnitSlotID::instance; + } + } } } UVar6 = this->units[_currentUnitID].unitType; @@ -569,16 +573,18 @@ namespace Map { *piVar1 = *piVar1 + 1; } DAT_UnitHasBecomeIdle::instance = 0; - if (((((this->units[uVar9].dying != 0) - && (this->units[uVar9].state.generic != OpenSHC::Map::Units::States::US_DISAPPEAR)) - && (UVar6 = this->units[uVar9].unitType, UVar6 != OpenSHC::Map::Units::UT_BURNINGMAN)) - && ((UVar6 != OpenSHC::Map::Units::UT_BURNING_ANIMAL_BIG - && (UVar6 != OpenSHC::Map::Units::UT_BURNING_ANIMAL_SMALL)))) - && (((short)this->units[uVar9].state.generic < 0x6f - || (0x75 < (short)this->units[uVar9].state.generic)))) { - this->units[uVar9].state.generic = OpenSHC::Map::Units::States::US_DEATH_01; - this->units[DAT_CurrentUnitSlotID::instance].animationCycleNumber = 0; - uVar9 = DAT_CurrentUnitSlotID::instance; + if (this->units[uVar9].dying != 0 + && this->units[uVar9].state.generic != OpenSHC::Map::Units::States::US_DISAPPEAR) { + UVar6 = this->units[uVar9].unitType; + if (UVar6 != OpenSHC::Map::Units::UT_BURNINGMAN + && UVar6 != OpenSHC::Map::Units::UT_BURNING_ANIMAL_BIG + && UVar6 != OpenSHC::Map::Units::UT_BURNING_ANIMAL_SMALL + && ((short)this->units[uVar9].state.generic < 0x6f + || 0x75 < (short)this->units[uVar9].state.generic)) { + this->units[uVar9].state.generic = OpenSHC::Map::Units::States::US_DEATH_01; + this->units[DAT_CurrentUnitSlotID::instance].animationCycleNumber = 0; + uVar9 = DAT_CurrentUnitSlotID::instance; + } } if (DAT_UnitPropertiesDefinedData::instance .COMPUTER_CONTROLLED[(short)this->units[uVar9].unitType] diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index bf086bf1c..05250db9d 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -66991,7 +66991,7 @@ SHC_3BB0A8C1_0x005792F8 | 0.0% | Pending SHC_3BB0A8C1_0x005792FC | 0.0% | Pending -SHC_3BB0A8C1_0x00579300 | 33.7% | reg alloc, dup tails +SHC_3BB0A8C1_0x00579300 | 34.1% | reg alloc, dup tails SHC_3BB0A8C1_0x00579380 | 0.0% | Pending From ed6abef376a05e270b750196be519d9054145f2f Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 21:50:02 +0200 Subject: [PATCH 247/299] reimplement: SHC_3BB0A8C1_0x0054B0D0 39.29% 2-reg addressing, reg alloc --- .../Units/UnitsState/acquireShootTarget.cpp | 25 +++++++++---------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/acquireShootTarget.cpp b/src/OpenSHC/Map/Units/UnitsState/acquireShootTarget.cpp index 2cd77bc5a..3c3520234 100644 --- a/src/OpenSHC/Map/Units/UnitsState/acquireShootTarget.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/acquireShootTarget.cpp @@ -169,10 +169,9 @@ namespace Map { (int)(this->units[_0x04_targetUnitID].microYPosition), (int)(this->units[_0x04_targetUnitID].buildingHeight + 0x1a + this->units[_0x04_targetUnitID].terrainOrClimbHeight)); - if (((_shootDistanceScore <= 0) - || (UVar4 = this->units[unitID].unitType, - UVar4 == OpenSHC::Map::Units::UT_S_MANGONEL)) - || (UVar4 == OpenSHC::Map::Units::UT_S_BALLISTA)) { + if (_shootDistanceScore <= 0 + || (UVar4 = this->units[unitID].unitType, UVar4 == OpenSHC::Map::Units::UT_S_MANGONEL) + || UVar4 == OpenSHC::Map::Units::UT_S_BALLISTA) { if (this->units[unitID].unitType == OpenSHC::Map::Units::UT_HUNTER) { return FALSE; } @@ -242,9 +241,9 @@ namespace Map { sVar9 = this->units[unitID].targetID_OR_targetBuildingID; int _brazierEntityID; - if ((DAT_TileMapState::instance.pitchDitches[sVar9].uid + if (DAT_TileMapState::instance.pitchDitches[sVar9].uid == this->units[unitID] - .targetedUnitUIDUnk_OR_someAppearTileUnk_OR_buildingUID_OR_pitchDitchUID_OR_entityUID) + .targetedUnitUIDUnk_OR_someAppearTileUnk_OR_buildingUID_OR_pitchDitchUID_OR_entityUID && (_brazierEntityID = MACRO_CALL_MEMBER(OpenSHC::Map::Entities::EntityState_Func::isBrazierNearby, DAT_EntityState::ptr)((int)this->units[unitID].x, (int)(this->units[unitID].y), (int)(( @@ -277,7 +276,7 @@ namespace Map { int _0x17_tile = DAT_ViewportRenderState::instance.translationMatrix[_0x17_y].addXgetTile + _0x17_x; BVar6 = MACRO_CALL_MEMBER(OpenSHC::Rendering::ViewportRenderState_Func::xyAreValid, DAT_ViewportRenderState::ptr)(_0x17_x, (uint)(_0x17_y)); - if ((BVar6 != FALSE) && ((DAT_TileMapState::instance.LogicLayer[_0x17_tile] & 0x100U) != 0)) { + if (BVar6 != FALSE && (DAT_TileMapState::instance.LogicLayer[_0x17_tile] & 0x100U) != 0) { this->units[unitID].shootTargetMicroX = this->units[unitID].attackAtTileX * 8; this->units[unitID].shootTargetMicroY = this->units[unitID].attackAtTileY * 8; this->units[unitID].shootTargetZ @@ -312,20 +311,20 @@ namespace Map { break; case OpenSHC::Map::Units::UT_LIONSHWOLF: sVar9 = this->units[_enemy].tribeID; - if ((DAT_TribesState::instance.tribes[sVar9].unknownBool02 != 0) - || ((DAT_TribesState::instance.tribes[sVar9].unknownBool01 == 0 + if (DAT_TribesState::instance.tribes[sVar9].unknownBool02 != 0 + || (DAT_TribesState::instance.tribes[sVar9].unknownBool01 == 0 && ((this->units[_enemy].state.generic != 0xcf || (this->units[this->units[_enemy] .targetedUnitID__OR__engineerMannedSiegeEngineRef] .isStalked - != 0)))))) + != 0))))) continue; break; case OpenSHC::Map::Units::UT_RABBIT: _xDifferenceToTarget = (int)this->units[unitID].tribeID; - if (((this->units[unitID].unitType == OpenSHC::Map::Units::UT_HUNTER) - || (_xDifferenceToTarget <= 0)) - || (DAT_TribesState::instance.tribes[_xDifferenceToTarget].field71_0x212 == 0)) + if (this->units[unitID].unitType == OpenSHC::Map::Units::UT_HUNTER + || _xDifferenceToTarget <= 0 + || DAT_TribesState::instance.tribes[_xDifferenceToTarget].field71_0x212 == 0) continue; break; case OpenSHC::Map::Units::UT_CAGEDOG: From 6281048d16e504b154b9f645c2b501d6a2fbcc83 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 21:50:03 +0200 Subject: [PATCH 248/299] reimplement: SHC_3BB0A8C1_0x00531920 25.58% extra spills, frame size --- .../UnitsState/processEntityDamageToUnit.cpp | 23 +++++++++---------- 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/processEntityDamageToUnit.cpp b/src/OpenSHC/Map/Units/UnitsState/processEntityDamageToUnit.cpp index c8fcc9621..6cb7ac477 100644 --- a/src/OpenSHC/Map/Units/UnitsState/processEntityDamageToUnit.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/processEntityDamageToUnit.cpp @@ -173,11 +173,11 @@ namespace Map { } _unitHeight = 42; } - if ((((_entityType == OpenSHC::Map::Entities::ET_TREBUCHET) - || (_entityType == OpenSHC::Map::Entities::ET_CATAPULT)) - || (_entityType == OpenSHC::Map::Entities::ET_MANGONEL)) - || ((_entityType == OpenSHC::Map::Entities::ET_BALLISTA - || (_entityType == OpenSHC::Map::Entities::ET_FIREBALLISTA)))) { + if (_entityType == OpenSHC::Map::Entities::ET_TREBUCHET + || _entityType == OpenSHC::Map::Entities::ET_CATAPULT + || _entityType == OpenSHC::Map::Entities::ET_MANGONEL + || _entityType == OpenSHC::Map::Entities::ET_BALLISTA + || _entityType == OpenSHC::Map::Entities::ET_FIREBALLISTA) { _siegeProjectile = 1; } short _unitPlayerID = this->units[unitID].owner; @@ -194,7 +194,7 @@ namespace Map { || (_unitType == OpenSHC::Map::Units::UT_S_SHIELD)) || (_unitType == OpenSHC::Map::Units::UT_S_TOWER)) || (_unitType == OpenSHC::Map::Units::UT_S_BATTERINGRAM)))))) - || (this->units[unitID].dying != 0)) { + || this->units[unitID].dying != 0) { return FALSE; } int _unitAltitude = (int)this->units[unitID].terrainOrClimbHeight + (int)this->units[unitID].buildingHeight; @@ -311,8 +311,8 @@ namespace Map { if (_entityType == OpenSHC::Map::Entities::ET_ARROW_AND_DEFAULT) { _entityType_2 = this->units[unitID].unitType; _damage = DAT_UnitPropertiesDefinedData::instance.ARROW_DAMAGE[(short)_entityType_2]; - if ((_entityType_2 == OpenSHC::Map::Units::UT_E_LADDER) - && (this->units[unitID].state.generic == ((UnitState)3))) { + if (_entityType_2 == OpenSHC::Map::Units::UT_E_LADDER + && this->units[unitID].state.generic == (UnitState)3) { _damage = (int)(_damage + (_damage >> 0x1f & 3U)) >> 2; } } else if (_entityType == OpenSHC::Map::Entities::ET_SLINGER) { @@ -371,10 +371,9 @@ namespace Map { this->units[unitID].healthPercentage = _entityShootingUnitID; this->units[unitID].healthbar = (_entityShootingUnitID / 10 + (_entityShootingUnitID >> 0xf)) - (short)((longlong)(int)_entityShootingUnitID * 0x66666667 >> 0x3f); - if ((((_unitType == OpenSHC::Map::Units::UT_BREWER) || (_unitType == OpenSHC::Map::Units::UT_TANNER)) - || (_unitType == OpenSHC::Map::Units::UT_LADY)) - || ((_unitType == OpenSHC::Map::Units::UT_MOTHER - || ((_unitType == OpenSHC::Map::Units::UT_CHILD && (this->units[unitID].spriteID == 0x81)))))) { + if (_unitType == OpenSHC::Map::Units::UT_BREWER || _unitType == OpenSHC::Map::Units::UT_TANNER + || _unitType == OpenSHC::Map::Units::UT_LADY || _unitType == OpenSHC::Map::Units::UT_MOTHER + || (_unitType == OpenSHC::Map::Units::UT_CHILD && (this->units[unitID].spriteID == 0x81))) { bVar4 = 1; } bool _shootingUnitID = this->units[_entityShootingUnitID_2].unitType == OpenSHC::Map::Units::UT_A_SLINGER; From bd1a6d68d9685def62e62258a50e050de5d85ef3 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 21:50:03 +0200 Subject: [PATCH 249/299] reimplement: SHC_3BB0A8C1_0x00549C70 29.20% mask reg alloc, frame ptr --- .../UnitsState/processMeleeInitiation.cpp | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/processMeleeInitiation.cpp b/src/OpenSHC/Map/Units/UnitsState/processMeleeInitiation.cpp index 43bc0eb85..c05c7c847 100644 --- a/src/OpenSHC/Map/Units/UnitsState/processMeleeInitiation.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/processMeleeInitiation.cpp @@ -50,16 +50,15 @@ namespace Map { } else { _distanceThreshold = 270; } - if (((this->units[unitID].closestEnemyMicroDistance <= _distanceThreshold) - || (this->units[unitID].attackedUnitID != 0)) - || ((this->units[unitID].unitType == OpenSHC::Map::Units::UT_LIONSHWOLF - || ((this->units[unitID].isStalked != 0 - && (((DAT_GameSynchronyState::instance.currentGameMode != OpenSHC::Game::GM_SOLITARY - || (100 < (int)this->unitCount)) - && (((this->units[unitID].fixedRng - ^ DAT_GameState::instance.mapAndTime.totalGameTicksUnk) - & 0xf) - == 0)))))))) { + if (this->units[unitID].closestEnemyMicroDistance <= _distanceThreshold + || this->units[unitID].attackedUnitID != 0 + || this->units[unitID].unitType == OpenSHC::Map::Units::UT_LIONSHWOLF + || (this->units[unitID].isStalked != 0 + && (((DAT_GameSynchronyState::instance.currentGameMode != OpenSHC::Game::GM_SOLITARY + || (100 < (int)this->unitCount)) + && (((this->units[unitID].fixedRng ^ DAT_GameState::instance.mapAndTime.totalGameTicksUnk) + & 0xf) + == 0))))) { _totalHeight = (int)this->units[unitID].buildingHeight + (int)this->units[unitID].terrainOrClimbHeight; int _playerID = (int)this->units[unitID].owner; From 44cbccaa5d48c902c3c81dc1e7ba117412afc01a Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 21:50:03 +0200 Subject: [PATCH 250/299] reimplement: SHC_3BB0A8C1_0x00579300 34.14% reg alloc, dup tails --- .../Map/Units/UnitsState/updateUnits.cpp | 86 +++++++++---------- 1 file changed, 42 insertions(+), 44 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/updateUnits.cpp b/src/OpenSHC/Map/Units/UnitsState/updateUnits.cpp index d031f4c93..f6d2abde9 100644 --- a/src/OpenSHC/Map/Units/UnitsState/updateUnits.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/updateUnits.cpp @@ -156,8 +156,8 @@ namespace Map { (int)(this->units[_currentUnitID].y), OpenSHC::DE::SHCDE::FX_CHICKEN_FLAP); _currentUnitID = DAT_CurrentUnitSlotID::instance; } - if ((999 < (int)(DAT_GameCore::instance.mapTimeInTicks - - this->units[_currentUnitID].time)) + if (999 < (int)(DAT_GameCore::instance.mapTimeInTicks + - this->units[_currentUnitID].time) && (_unitType = this->units[_currentUnitID].unitType, _unitType != OpenSHC::Map::Units::UT_S_TOWER)) { if (_unitType == OpenSHC::Map::Units::UT_LORD) { @@ -187,16 +187,16 @@ namespace Map { UVar6 = this->units[_currentUnitID].unitType; if (((UVar6 == OpenSHC::Map::Units::UT_S_CATAPULT) || (UVar6 == OpenSHC::Map::Units::UT_S_FBALLISTA)) - && ((DAT_TileMapState::instance.LogicLayer[this->units[_currentUnitID].tile] & 0x50000000U) - != 0)) { + && (DAT_TileMapState::instance.LogicLayer[this->units[_currentUnitID].tile] & 0x50000000U) + != 0) { this->units[_currentUnitID].state.generic = OpenSHC::Map::Units::States::US_DISAPPEAR; this->units[DAT_CurrentUnitSlotID::instance].updateTickTracker = 0; _currentUnitID = DAT_CurrentUnitSlotID::instance; } } - if ((this->units[_currentUnitID].logicalState == OpenSHC::Map::Units::ULS_NORMAL) - && (((this->units[_currentUnitID].x == 0 || (this->units[_currentUnitID].y == 0)) - || (this->units[_currentUnitID].tile < 0)))) { + if (this->units[_currentUnitID].logicalState == OpenSHC::Map::Units::ULS_NORMAL + && ((this->units[_currentUnitID].x == 0 || (this->units[_currentUnitID].y == 0)) + || (this->units[_currentUnitID].tile < 0))) { this->units[_currentUnitID].state.generic = OpenSHC::Map::Units::States::US_DISAPPEAR; this->units[DAT_CurrentUnitSlotID::instance].updateTickTracker = 0; _currentUnitID = DAT_CurrentUnitSlotID::instance; @@ -442,20 +442,20 @@ namespace Map { } } _buildingID = this->units[uVar9].unitType; - if ((((_buildingID == OpenSHC::Map::Units::UT_E_ARCHER) - || (_buildingID == OpenSHC::Map::Units::UT_A_ARCHER)) - && ((_buildingID = this->units[uVar9].state.generic, - _buildingID == OpenSHC::Map::Units::States::US_AIM_WEAPONUnk - || (_buildingID == OpenSHC::Map::Units::States::US_FIRE_WEAPONUnk)))) - && ((_troopValue = this->units[uVar9].shootTargetedUnit, - 0 < _troopValue && (this->units[_troopValue].uid == this->units[uVar9].targetUID)))) { + if (((_buildingID == OpenSHC::Map::Units::UT_E_ARCHER) + || (_buildingID == OpenSHC::Map::Units::UT_A_ARCHER)) + && (_buildingID = this->units[uVar9].state.generic, + _buildingID == OpenSHC::Map::Units::States::US_AIM_WEAPONUnk + || (_buildingID == OpenSHC::Map::Units::States::US_FIRE_WEAPONUnk)) + && (_troopValue = this->units[uVar9].shootTargetedUnit, + 0 < _troopValue && (this->units[_troopValue].uid == this->units[uVar9].targetUID))) { this->units[_troopValue].field233_0x39a = 1; uVar9 = DAT_CurrentUnitSlotID::instance; } - if ((this->units[uVar9].enemyNoticeFrequencyUnk != 0) - && ((DAT_GameState::instance.mapAndTime.totalGameTicksUnk - & this->units[uVar9].enemyNoticeFrequencyUnk) - == (this->units[uVar9].fixedRng & this->units[uVar9].enemyNoticeFrequencyUnk))) { + if (this->units[uVar9].enemyNoticeFrequencyUnk != 0 + && (DAT_GameState::instance.mapAndTime.totalGameTicksUnk + & this->units[uVar9].enemyNoticeFrequencyUnk) + == (this->units[uVar9].fixedRng & this->units[uVar9].enemyNoticeFrequencyUnk)) { if (this->units[uVar9].owner == 0) { _troopValue = MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func:: computeDistanceToNearestEnemyForLegacyMissions, @@ -525,7 +525,7 @@ namespace Map { == OpenSHC::Map::Units::ULS_TRANSITIONING) { MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::changeUnitType, this)( DAT_CurrentUnitSlotID::instance); - } else if (this->units[DAT_CurrentUnitSlotID::instance].logicalState == ((UnitLogicState)1)) { + } else if (this->units[DAT_CurrentUnitSlotID::instance].logicalState == (UnitLogicState)1) { this->units[DAT_CurrentUnitSlotID::instance].logicalState = OpenSHC::Map::Units::ULS_NORMAL; } int* _ptr_animationTicker = &this->units[DAT_CurrentUnitSlotID::instance].animationTicker; @@ -645,12 +645,12 @@ namespace Map { } uVar9 = DAT_CurrentUnitSlotID::instance; UnitStateShort UVar8 = this->units[DAT_CurrentUnitSlotID::instance].field143_0x2c4; - if (((UVar8 != this->units[DAT_CurrentUnitSlotID::instance].state.generic) - && ((UVar8 - == (OpenSHC::Map::Units::States::US_DEATH_02 - | OpenSHC::Map::Units::States::US_STAND_UPUnk - | OpenSHC::Map::Units::States::US_RELOAD_WEAPONUnk) - || (UVar8 == OpenSHC::Map::Units::States::US_DIG)))) + if (UVar8 != this->units[DAT_CurrentUnitSlotID::instance].state.generic + && (UVar8 + == (OpenSHC::Map::Units::States::US_DEATH_02 + | OpenSHC::Map::Units::States::US_STAND_UPUnk + | OpenSHC::Map::Units::States::US_RELOAD_WEAPONUnk) + || (UVar8 == OpenSHC::Map::Units::States::US_DIG)) && (_troopValue = this->units[DAT_CurrentUnitSlotID::instance].digTileTarget, DAT_TileMapState::instance.moats[_troopValue].owner != '\0')) { char* pcVar3 = &DAT_TileMapState::instance.moats[_troopValue].someCountDown; @@ -680,11 +680,10 @@ namespace Map { this)(DAT_CurrentUnitSlotID::instance, (int)(this->units[DAT_CurrentUnitSlotID::instance].stateBasedSpeed)); if (_troopValue != 0) { - if (((this->units[DAT_CurrentUnitSlotID::instance].state.generic - == OpenSHC::Map::Units::States::US_MOVE_TO_DESTINATION) - && (this->units[DAT_CurrentUnitSlotID::instance].disappearFadeAlphaCountdown - != 0)) - && (this->units[DAT_CurrentUnitSlotID::instance].fadeType == 0)) { + if (this->units[DAT_CurrentUnitSlotID::instance].state.generic + == OpenSHC::Map::Units::States::US_MOVE_TO_DESTINATION + && this->units[DAT_CurrentUnitSlotID::instance].disappearFadeAlphaCountdown != 0 + && this->units[DAT_CurrentUnitSlotID::instance].fadeType == 0) { this->units[DAT_CurrentUnitSlotID::instance].disappearFadeAlphaCountdown = 0; } psVar4 = &this->units[DAT_CurrentUnitSlotID::instance].field218_0x37e; @@ -739,12 +738,12 @@ namespace Map { + this->units[DAT_CurrentUnitSlotID::instance].animationSheetFrameOffset; piVar1 = &this->units[DAT_CurrentUnitSlotID::instance].gfxNumber; *piVar1 = *piVar1 + this->units[DAT_CurrentUnitSlotID::instance].field215_0x378 * 8; - if (((this->units[DAT_CurrentUnitSlotID::instance].unitType - == OpenSHC::Map::Units::UT_A_HARCHER) - && (_buildingID - = this->units[DAT_CurrentUnitSlotID::instance].horseArcherShootingVariation, - _buildingID != 4)) - && ((_buildingID != 5 && (_buildingID != 6)))) { + if (this->units[DAT_CurrentUnitSlotID::instance].unitType + == OpenSHC::Map::Units::UT_A_HARCHER + && (_buildingID + = this->units[DAT_CurrentUnitSlotID::instance].horseArcherShootingVariation, + _buildingID != 4) + && _buildingID != 5 && _buildingID != 6) { this->units[DAT_CurrentUnitSlotID::instance].imageIDUnk = this->units[DAT_CurrentUnitSlotID::instance].gfxNumber; } @@ -790,15 +789,14 @@ namespace Map { this->units[DAT_CurrentUnitSlotID::instance].imageIDUnk = this->units[DAT_CurrentUnitSlotID::instance].gfxNumber; if ((DAT_CurrentUnitSlotID::instance & 1) == 0) { - if (((this->units[DAT_CurrentUnitSlotID::instance].stateBasedSpeed != 0) - && ((this->units[DAT_CurrentUnitSlotID::instance] - .movementType_OR_targetUnitID - != 0 - || (this->units[DAT_CurrentUnitSlotID::instance].targetingType - == OpenSHC::Map::Units::UIT_UNIT_ATTACK_UNIT)))) - && (this->units[DAT_CurrentUnitSlotID::instance].totalSizeOfPathPlan + -0x10 + if (this->units[DAT_CurrentUnitSlotID::instance].stateBasedSpeed != 0 + && (this->units[DAT_CurrentUnitSlotID::instance].movementType_OR_targetUnitID + != 0 + || (this->units[DAT_CurrentUnitSlotID::instance].targetingType + == OpenSHC::Map::Units::UIT_UNIT_ATTACK_UNIT)) + && this->units[DAT_CurrentUnitSlotID::instance].totalSizeOfPathPlan + -0x10 <= (int)this->units[DAT_CurrentUnitSlotID::instance] - .currentIndexInPathPlan)) { + .currentIndexInPathPlan) { piVar1 = &this->units[DAT_CurrentUnitSlotID::instance].imageIDUnk; *piVar1 = *piVar1 + 0x80; } From bacf39e0d85ffa3133ea5255468a47b332539fc1 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 23:50:45 +0200 Subject: [PATCH 251/299] reimplement: SHC_3BB0A8C1_0x00534520 21.28% spills base+tile to stack --- .../writeSixToTileMap1104InAllDirections.cpp | 27 ++++++++++++------- status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/writeSixToTileMap1104InAllDirections.cpp b/src/OpenSHC/Map/Units/UnitsState/writeSixToTileMap1104InAllDirections.cpp index 6eb72134b..11b1d0a1d 100644 --- a/src/OpenSHC/Map/Units/UnitsState/writeSixToTileMap1104InAllDirections.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/writeSixToTileMap1104InAllDirections.cpp @@ -9,16 +9,23 @@ namespace Map { // FUNCTION: STRONGHOLDCRUSADER 0x00534520 void UnitsState::writeSixToTileMap1104InAllDirections(int unitID, undefined4 six) { - DAT_TileMapState::instance.SEC_TileMap1104[this->units[unitID].tile + 1] = (uchar)six; - DAT_TileMapState::instance.SEC_TileMap1104[this->units[unitID].tile - 1] = (uchar)six; - DAT_TileMapState::instance.SEC_TileMap1104[this->units[unitID].tile] = (uchar)six; - for (int row = 0; row < 8; row += 4) { - int _rowOffset = ((int*)DAT_TileMapState::instance - .ptr_MovementDirectionTranslationMatrix)[this->units[unitID].y * 8 + row]; - DAT_TileMapState::instance.SEC_TileMap1104[this->units[unitID].tile + _rowOffset - 1] = (uchar)six; - DAT_TileMapState::instance.SEC_TileMap1104[this->units[unitID].tile + _rowOffset + 1] = (uchar)six; - DAT_TileMapState::instance.SEC_TileMap1104[this->units[unitID].tile + _rowOffset] = (uchar)six; - } + uchar* _tileTypes = DAT_TileMapState::instance.SEC_TileMap1104; + int _tile = this->units[unitID].tile; + int _y = this->units[unitID].y; + uchar* _ownRow = _tileTypes + _tile; + _ownRow[1] = (uchar)six; + _ownRow[-1] = (uchar)six; + _ownRow[0] = (uchar)six; + int* _directionRow + = (int*)((uchar*)DAT_TileMapState::instance.ptr_MovementDirectionTranslationMatrix + _y * 0x20); + uchar* _nextRow = _ownRow + _directionRow[0]; + _nextRow[-1] = (uchar)six; + _nextRow[1] = (uchar)six; + _nextRow[0] = (uchar)six; + uchar* _furtherRow = _ownRow + _directionRow[4]; + _furtherRow[-1] = (uchar)six; + _furtherRow[1] = (uchar)six; + _furtherRow[0] = (uchar)six; } } diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 05250db9d..b4c94a1e2 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -50813,7 +50813,7 @@ SHC_3BB0A8C1_0x00534460 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00534490 | 15.4% | orig unrolled, 16-bit ORs -SHC_3BB0A8C1_0x00534520 | 17.4% | orig unrolled, not a loop +SHC_3BB0A8C1_0x00534520 | 21.3% | spills base+tile to stack SHC_3BB0A8C1_0x005345A0 | 61.7% | orig walks unit ptr From c6f27c338a7994e2b1f4ea1919c061d358a19318 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 23:52:53 +0200 Subject: [PATCH 252/299] reimplement: SHC_3BB0A8C1_0x00534490 20.41% spills base+tile, word OR --- .../stampOccupancyFlagOnSurroundingTiles.cpp | 33 ++++++++++--------- status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/stampOccupancyFlagOnSurroundingTiles.cpp b/src/OpenSHC/Map/Units/UnitsState/stampOccupancyFlagOnSurroundingTiles.cpp index bcf19808c..5b4526799 100644 --- a/src/OpenSHC/Map/Units/UnitsState/stampOccupancyFlagOnSurroundingTiles.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/stampOccupancyFlagOnSurroundingTiles.cpp @@ -9,21 +9,24 @@ namespace Map { // FUNCTION: STRONGHOLDCRUSADER 0x00534490 void UnitsState::stampOccupancyFlagOnSurroundingTiles(int unitID) { - DAT_TileMapState::instance.OccupancyLayer[this->units[unitID].tile + 1] - |= this->units[unitID].occupancyOrFlag; - DAT_TileMapState::instance.OccupancyLayer[this->units[unitID].tile - 1] - |= this->units[unitID].occupancyOrFlag; - DAT_TileMapState::instance.OccupancyLayer[this->units[unitID].tile] |= this->units[unitID].occupancyOrFlag; - for (int row = 0; row < 8; row += 4) { - int _rowOffset = ((int*)DAT_TileMapState::instance - .ptr_MovementDirectionTranslationMatrix)[this->units[unitID].y * 8 + row]; - DAT_TileMapState::instance.OccupancyLayer[this->units[unitID].tile + _rowOffset - 1] - |= this->units[unitID].occupancyOrFlag; - DAT_TileMapState::instance.OccupancyLayer[this->units[unitID].tile + _rowOffset + 1] - |= this->units[unitID].occupancyOrFlag; - DAT_TileMapState::instance.OccupancyLayer[this->units[unitID].tile + _rowOffset] - |= this->units[unitID].occupancyOrFlag; - } + uchar* _occupancy = DAT_TileMapState::instance.OccupancyLayer; + int _tile = this->units[unitID].tile; + int _y = this->units[unitID].y; + uchar _flag = this->units[unitID].occupancyOrFlag; + uchar* _ownRow = _occupancy + _tile; + _ownRow[1] |= _flag; + _ownRow[-1] |= _flag; + _ownRow[0] |= _flag; + int* _directionRow + = (int*)((uchar*)DAT_TileMapState::instance.ptr_MovementDirectionTranslationMatrix + _y * 0x20); + uchar* _nextRow = _ownRow + _directionRow[0]; + _nextRow[-1] |= _flag; + _nextRow[1] |= _flag; + _nextRow[0] |= _flag; + uchar* _furtherRow = _ownRow + _directionRow[4]; + _furtherRow[-1] |= _flag; + _furtherRow[1] |= _flag; + _furtherRow[0] |= _flag; } } diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index b4c94a1e2..5eb274664 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -50811,7 +50811,7 @@ SHC_3BB0A8C1_0x005343F0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00534460 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x00534490 | 15.4% | orig unrolled, 16-bit ORs +SHC_3BB0A8C1_0x00534490 | 20.4% | spills base+tile, word OR SHC_3BB0A8C1_0x00534520 | 21.3% | spills base+tile to stack From ac3752c157b267774ec2304d125fdf39f57b4e82 Mon Sep 17 00:00:00 2001 From: Gynt Date: Sun, 27 Sep 2026 23:56:35 +0200 Subject: [PATCH 253/299] reimplement: SHC_3BB0A8C1_0x00532F80 43.31% block order, spills --- ...istanceToNearestEnemyForLegacyMissions.cpp | 67 ++++++++++--------- status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 36 insertions(+), 33 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/computeDistanceToNearestEnemyForLegacyMissions.cpp b/src/OpenSHC/Map/Units/UnitsState/computeDistanceToNearestEnemyForLegacyMissions.cpp index 326fb3e15..daf253ff9 100644 --- a/src/OpenSHC/Map/Units/UnitsState/computeDistanceToNearestEnemyForLegacyMissions.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/computeDistanceToNearestEnemyForLegacyMissions.cpp @@ -13,42 +13,45 @@ namespace Map { // FUNCTION: STRONGHOLDCRUSADER 0x00532F80 int UnitsState::computeDistanceToNearestEnemyForLegacyMissions(int unitID) { - if (DAT_GameSynchronyState::instance.currentGameMode != OpenSHC::Game::GM_SOLITARY) { - return 10000; - } - if ((int)this->unitCount >= 100) { - return 10000; - } - short _owner = this->units[unitID].owner; - int _unitMicroX = this->units[unitID].microXPosition; + int _owner = this->units[unitID].owner; int _unitMicroY = this->units[unitID].microYPosition; + int _unitMicroX = this->units[unitID].microXPosition; + /* kept in step with the result but never read back */ + int _closestWithinThousand = 1000; int _closestDistance = 10000; - for (int i = 0; i < DAT_GameState::instance.playerDataArray[_owner].enemies; ++i) { - short _enemyUnitID = DAT_GameState::instance.playerDataArray[_owner].enemyIDArray[i]; - if (this->units[_enemyUnitID].uid - != DAT_GameState::instance.mapAndTime.playerEnemenyUnitUIDShortList[_owner][i]) { - continue; - } - int _distanceX = this->units[_enemyUnitID].microXPosition; - if (_distanceX < _unitMicroX) { - _distanceX = _unitMicroX - _distanceX; - } else { - _distanceX = _distanceX - _unitMicroX; - } - int _distanceY = this->units[_enemyUnitID].microYPosition; - if (_distanceY < _unitMicroY) { - _distanceY = _unitMicroY - _distanceY; - } else { - _distanceY = _distanceY - _unitMicroY; - } - if (_distanceY <= _distanceX) { - _distanceY = _distanceX; - } - if (_distanceY < _closestDistance) { - _closestDistance = _distanceY; + if (DAT_GameSynchronyState::instance.currentGameMode == OpenSHC::Game::GM_SOLITARY + && (int)this->unitCount <= 100) { + for (int i = 0; i < DAT_GameState::instance.playerDataArray[_owner].enemies; ++i) { + int _enemyUnitID = DAT_GameState::instance.playerDataArray[_owner].enemyIDArray[i]; + if (this->units[_enemyUnitID].uid + != DAT_GameState::instance.mapAndTime.playerEnemenyUnitUIDShortList[_owner][i]) { + continue; + } + int _distanceX = this->units[_enemyUnitID].microXPosition; + if (_distanceX < _unitMicroX) { + _distanceX = _unitMicroX - _distanceX; + } else { + _distanceX = _distanceX - _unitMicroX; + } + int _distanceY = this->units[_enemyUnitID].microYPosition; + if (_distanceY < _unitMicroY) { + _distanceY = _unitMicroY - _distanceY; + } else { + _distanceY = _distanceY - _unitMicroY; + } + if (_distanceY <= _distanceX) { + _distanceY = _distanceX; + } + if (_distanceY < _closestWithinThousand) { + _closestWithinThousand = _distanceY; + } + if (_distanceY < _closestDistance) { + _closestDistance = _distanceY; + } } + return _closestDistance; } - return _closestDistance; + return 10000; } } diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 5eb274664..058f29367 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -50645,7 +50645,7 @@ SHC_3BB0A8C1_0x00532F5E | 0.0% | Pending SHC_3BB0A8C1_0x00532F60 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x00532F80 | 12.6% | orig walks 2 arrays by ptr +SHC_3BB0A8C1_0x00532F80 | 43.3% | block order, spills SHC_3BB0A8C1_0x00533010 | 0.0% | Pending From 7340a656d9f6c4ee7df90c012958498f9e23adfb Mon Sep 17 00:00:00 2001 From: Gynt Date: Mon, 28 Sep 2026 00:07:41 +0200 Subject: [PATCH 254/299] reimplement: SHC_3BB0A8C1_0x00534520 22.22% spills base+tile to stack --- .../writeSixToTileMap1104InAllDirections.cpp | 20 +++++++++---------- status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/writeSixToTileMap1104InAllDirections.cpp b/src/OpenSHC/Map/Units/UnitsState/writeSixToTileMap1104InAllDirections.cpp index 11b1d0a1d..502de87d7 100644 --- a/src/OpenSHC/Map/Units/UnitsState/writeSixToTileMap1104InAllDirections.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/writeSixToTileMap1104InAllDirections.cpp @@ -9,23 +9,23 @@ namespace Map { // FUNCTION: STRONGHOLDCRUSADER 0x00534520 void UnitsState::writeSixToTileMap1104InAllDirections(int unitID, undefined4 six) { - uchar* _tileTypes = DAT_TileMapState::instance.SEC_TileMap1104; + uchar* _tileMap1104 = DAT_TileMapState::instance.SEC_TileMap1104; int _tile = this->units[unitID].tile; int _y = this->units[unitID].y; - uchar* _ownRow = _tileTypes + _tile; - _ownRow[1] = (uchar)six; - _ownRow[-1] = (uchar)six; - _ownRow[0] = (uchar)six; + uchar* _row = _tileMap1104 + _tile; + _row[1] = (uchar)six; + _row[-1] = (uchar)six; + _row[0] = (uchar)six; int* _directionRow = (int*)((uchar*)DAT_TileMapState::instance.ptr_MovementDirectionTranslationMatrix + _y * 0x20); - uchar* _nextRow = _ownRow + _directionRow[0]; + uchar* _nextRow = _row + _directionRow[0]; _nextRow[-1] = (uchar)six; _nextRow[1] = (uchar)six; _nextRow[0] = (uchar)six; - uchar* _furtherRow = _ownRow + _directionRow[4]; - _furtherRow[-1] = (uchar)six; - _furtherRow[1] = (uchar)six; - _furtherRow[0] = (uchar)six; + _row = _row + _directionRow[4]; + _row[-1] = (uchar)six; + _row[1] = (uchar)six; + _row[0] = (uchar)six; } } diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 058f29367..857ee5cb3 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -50813,7 +50813,7 @@ SHC_3BB0A8C1_0x00534460 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00534490 | 20.4% | spills base+tile, word OR -SHC_3BB0A8C1_0x00534520 | 21.3% | spills base+tile to stack +SHC_3BB0A8C1_0x00534520 | 22.2% | spills base+tile to stack SHC_3BB0A8C1_0x005345A0 | 61.7% | orig walks unit ptr From 47700813b917ed673ccd3cdd6f0cd348ac4da85d Mon Sep 17 00:00:00 2001 From: Gynt Date: Mon, 28 Sep 2026 00:11:25 +0200 Subject: [PATCH 255/299] reimplement: SHC_3BB0A8C1_0x0052F7E0 26.43% reg alloc, band order --- .../UnitsState/calculateUnitMovementSpeed.cpp | 67 ++++++++++++------- status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 42 insertions(+), 27 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/calculateUnitMovementSpeed.cpp b/src/OpenSHC/Map/Units/UnitsState/calculateUnitMovementSpeed.cpp index 3e7f3a183..1d0c46af4 100644 --- a/src/OpenSHC/Map/Units/UnitsState/calculateUnitMovementSpeed.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/calculateUnitMovementSpeed.cpp @@ -50,42 +50,57 @@ namespace Map { this->units[unitID].calculatedMovementSpeed = this->units[unitID].movementSpeed; } else if (this->units[unitID].terrainOrClimbHeight < (int)(uint)_tileHeight) { int _heightDifference = (uint)_tileHeight - this->units[unitID].terrainOrClimbHeight; - if (_heightDifference > 0x10) { + /* the climb bands are split by halving, not as a flat ladder */ + if (_heightDifference < 0x11) { + if (_heightDifference < 0xc) { + if (_heightDifference < 8) { + if (_heightDifference < 4) { + if (_heightDifference < 2) { + this->units[unitID].terrainOrClimbHeight + = this->units[unitID].terrainOrClimbHeight + 1; + this->units[unitID].calculatedMovementSpeed = this->units[unitID].movementSpeed; + } else { + this->units[unitID].terrainOrClimbHeight + = this->units[unitID].terrainOrClimbHeight + 2; + this->units[unitID].calculatedMovementSpeed = this->units[unitID].movementSpeed + 1; + } + } else { + this->units[unitID].terrainOrClimbHeight = this->units[unitID].terrainOrClimbHeight + 3; + this->units[unitID].calculatedMovementSpeed = this->units[unitID].movementSpeed + 3; + } + } else { + this->units[unitID].terrainOrClimbHeight = this->units[unitID].terrainOrClimbHeight + 4; + this->units[unitID].calculatedMovementSpeed = this->units[unitID].movementSpeed + 4; + this->units[unitID].movementRunUpTime = 8; + } + } else { + this->units[unitID].terrainOrClimbHeight = this->units[unitID].terrainOrClimbHeight + 4; + this->units[unitID].calculatedMovementSpeed = this->units[unitID].movementSpeed + 5; + this->units[unitID].movementRunUpTime = 0xc; + } + } else { this->units[unitID].terrainOrClimbHeight = _tileHeight; this->units[unitID].calculatedMovementSpeed = this->units[unitID].movementSpeed; - } else if (_heightDifference < 2) { - this->units[unitID].terrainOrClimbHeight = this->units[unitID].terrainOrClimbHeight + 1; - this->units[unitID].calculatedMovementSpeed = this->units[unitID].movementSpeed; - } else if (_heightDifference < 4) { - this->units[unitID].calculatedMovementSpeed = this->units[unitID].movementSpeed + 1; - this->units[unitID].terrainOrClimbHeight = this->units[unitID].terrainOrClimbHeight + 2; - } else if (_heightDifference < 8) { - this->units[unitID].calculatedMovementSpeed = this->units[unitID].movementSpeed + 3; - this->units[unitID].terrainOrClimbHeight = this->units[unitID].terrainOrClimbHeight + 3; - } else if (_heightDifference < 0xc) { - this->units[unitID].calculatedMovementSpeed = this->units[unitID].movementSpeed + 4; - this->units[unitID].terrainOrClimbHeight = this->units[unitID].terrainOrClimbHeight + 4; - this->units[unitID].movementRunUpTime = 8; - } else { - this->units[unitID].calculatedMovementSpeed = this->units[unitID].movementSpeed + 5; - this->units[unitID].terrainOrClimbHeight = this->units[unitID].terrainOrClimbHeight + 4; - this->units[unitID].movementRunUpTime = 0xc; } } else if ((int)(uint)_tileHeight < this->units[unitID].terrainOrClimbHeight) { int _heightDifference = this->units[unitID].terrainOrClimbHeight - (uint)_tileHeight; if (_heightDifference > 0x10) { this->units[unitID].terrainOrClimbHeight = _tileHeight; this->units[unitID].calculatedMovementSpeed = this->units[unitID].movementSpeed; - } else if (_heightDifference < 4) { - this->units[unitID].terrainOrClimbHeight = this->units[unitID].terrainOrClimbHeight - 1; - } else if (_heightDifference < 8) { - this->units[unitID].terrainOrClimbHeight = this->units[unitID].terrainOrClimbHeight - 2; - this->units[unitID].calculatedMovementSpeed = this->units[unitID].movementSpeed; } else if (_heightDifference < 0xc) { - this->units[unitID].terrainOrClimbHeight = this->units[unitID].terrainOrClimbHeight - 3; - this->units[unitID].calculatedMovementSpeed = this->units[unitID].movementSpeed; + if (_heightDifference < 8) { + if (_heightDifference > 3) { + this->units[unitID].terrainOrClimbHeight = this->units[unitID].terrainOrClimbHeight + -2; + this->units[unitID].calculatedMovementSpeed = this->units[unitID].movementSpeed; + } else { + this->units[unitID].terrainOrClimbHeight = this->units[unitID].terrainOrClimbHeight + -1; + } + } else { + this->units[unitID].terrainOrClimbHeight = this->units[unitID].terrainOrClimbHeight + -3; + this->units[unitID].calculatedMovementSpeed = this->units[unitID].movementSpeed; + } } else { - this->units[unitID].terrainOrClimbHeight = this->units[unitID].terrainOrClimbHeight - 4; + this->units[unitID].terrainOrClimbHeight = this->units[unitID].terrainOrClimbHeight + -4; this->units[unitID].calculatedMovementSpeed = this->units[unitID].movementSpeed; } } else if (this->units[unitID].isSelectable_OR_matchTime == 0) { diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 857ee5cb3..d369f5899 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -49343,7 +49343,7 @@ SHC_3BB0A8C1_0x0052F6C0 | 0.0% | Pending SHC_3BB0A8C1_0x0052F730 | 82.8% | reg alloc -SHC_3BB0A8C1_0x0052F7E0 | 17.6% | orig caches height locals +SHC_3BB0A8C1_0x0052F7E0 | 26.4% | reg alloc, band order SHC_3BB0A8C1_0x0052FBB0 | 100.0% | Reimplemented From 78fc4e03e2b5ba95cafa7b929ed50a053a1a3e77 Mon Sep 17 00:00:00 2001 From: Gynt Date: Mon, 28 Sep 2026 00:19:57 +0200 Subject: [PATCH 256/299] reimplement: SHC_3BB0A8C1_0x00534520 22.22% spills base+tile to stack --- .../writeSixToTileMap1104InAllDirections.cpp | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/writeSixToTileMap1104InAllDirections.cpp b/src/OpenSHC/Map/Units/UnitsState/writeSixToTileMap1104InAllDirections.cpp index 502de87d7..136ad028b 100644 --- a/src/OpenSHC/Map/Units/UnitsState/writeSixToTileMap1104InAllDirections.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/writeSixToTileMap1104InAllDirections.cpp @@ -9,23 +9,24 @@ namespace Map { // FUNCTION: STRONGHOLDCRUSADER 0x00534520 void UnitsState::writeSixToTileMap1104InAllDirections(int unitID, undefined4 six) { - uchar* _tileMap1104 = DAT_TileMapState::instance.SEC_TileMap1104; int _tile = this->units[unitID].tile; + uchar* _tileMap1104 = DAT_TileMapState::instance.SEC_TileMap1104; int _y = this->units[unitID].y; + uchar _value = (uchar)six; uchar* _row = _tileMap1104 + _tile; - _row[1] = (uchar)six; - _row[-1] = (uchar)six; - _row[0] = (uchar)six; + _row[1] = _value; + _row[-1] = _value; + _row[0] = _value; int* _directionRow = (int*)((uchar*)DAT_TileMapState::instance.ptr_MovementDirectionTranslationMatrix + _y * 0x20); uchar* _nextRow = _row + _directionRow[0]; - _nextRow[-1] = (uchar)six; - _nextRow[1] = (uchar)six; - _nextRow[0] = (uchar)six; + _nextRow[-1] = _value; + _nextRow[1] = _value; + _nextRow[0] = _value; _row = _row + _directionRow[4]; - _row[-1] = (uchar)six; - _row[1] = (uchar)six; - _row[0] = (uchar)six; + _row[-1] = _value; + _row[1] = _value; + _row[0] = _value; } } From ed86987908380990a7cc6c287094ede59823f460 Mon Sep 17 00:00:00 2001 From: Gynt Date: Mon, 28 Sep 2026 00:19:58 +0200 Subject: [PATCH 257/299] reimplement: SHC_3BB0A8C1_0x00534490 20.41% spills base+tile, word OR --- .../stampOccupancyFlagOnSurroundingTiles.cpp | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/stampOccupancyFlagOnSurroundingTiles.cpp b/src/OpenSHC/Map/Units/UnitsState/stampOccupancyFlagOnSurroundingTiles.cpp index 5b4526799..8f285e92d 100644 --- a/src/OpenSHC/Map/Units/UnitsState/stampOccupancyFlagOnSurroundingTiles.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/stampOccupancyFlagOnSurroundingTiles.cpp @@ -9,24 +9,24 @@ namespace Map { // FUNCTION: STRONGHOLDCRUSADER 0x00534490 void UnitsState::stampOccupancyFlagOnSurroundingTiles(int unitID) { - uchar* _occupancy = DAT_TileMapState::instance.OccupancyLayer; int _tile = this->units[unitID].tile; + uchar* _occupancy = DAT_TileMapState::instance.OccupancyLayer; int _y = this->units[unitID].y; - uchar _flag = this->units[unitID].occupancyOrFlag; - uchar* _ownRow = _occupancy + _tile; - _ownRow[1] |= _flag; - _ownRow[-1] |= _flag; - _ownRow[0] |= _flag; + uchar _value = this->units[unitID].occupancyOrFlag; + uchar* _row = _occupancy + _tile; + _row[1] |= _value; + _row[-1] |= _value; + _row[0] |= _value; int* _directionRow = (int*)((uchar*)DAT_TileMapState::instance.ptr_MovementDirectionTranslationMatrix + _y * 0x20); - uchar* _nextRow = _ownRow + _directionRow[0]; - _nextRow[-1] |= _flag; - _nextRow[1] |= _flag; - _nextRow[0] |= _flag; - uchar* _furtherRow = _ownRow + _directionRow[4]; - _furtherRow[-1] |= _flag; - _furtherRow[1] |= _flag; - _furtherRow[0] |= _flag; + uchar* _nextRow = _row + _directionRow[0]; + _nextRow[-1] |= _value; + _nextRow[1] |= _value; + _nextRow[0] |= _value; + uchar* _furtherRow = _row + _directionRow[4]; + _furtherRow[-1] |= _value; + _furtherRow[1] |= _value; + _furtherRow[0] |= _value; } } From 3ea5224fb55ae83b6ee9edfe3da14ad3b33f5256 Mon Sep 17 00:00:00 2001 From: Gynt Date: Mon, 28 Sep 2026 00:35:43 +0200 Subject: [PATCH 258/299] reimplement: SHC_3BB0A8C1_0x0054B0D0 39.29% 2-reg addressing, reg alloc --- .../Units/UnitsState/acquireShootTarget.cpp | 48 ------------------- 1 file changed, 48 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/acquireShootTarget.cpp b/src/OpenSHC/Map/Units/UnitsState/acquireShootTarget.cpp index 3c3520234..3a5f09ff4 100644 --- a/src/OpenSHC/Map/Units/UnitsState/acquireShootTarget.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/acquireShootTarget.cpp @@ -46,30 +46,14 @@ namespace Map { int local_2c = 100000; int local_10 = 0; int local_c = 0; - /* - switch based on unit type - */ - switch (this->units[unitID].unitType) { case OpenSHC::Map::Units::UT_E_XBOW: - /* - crossbow - */ - _entityType = 7; break; default: - /* - default: - */ - _entityType = 1; break; case OpenSHC::Map::Units::UT_S_CATAPULT: - /* - catapult - */ - _entityType = 2; if ((this->units[unitID].stoneAmmunition <= 0) && (this->units[unitID].targetingType != OpenSHC::Map::Units::UIT_THROW_COW)) { @@ -78,10 +62,6 @@ namespace Map { } break; case OpenSHC::Map::Units::UT_S_TREBUCHET: - /* - trebuchet - */ - _entityType = 3; if ((this->units[unitID].stoneAmmunition <= 0) && (this->units[unitID].targetingType != OpenSHC::Map::Units::UIT_THROW_COW)) { @@ -90,38 +70,18 @@ namespace Map { } break; case OpenSHC::Map::Units::UT_S_MANGONEL: - /* - mangonel - */ - _entityType = 4; break; case OpenSHC::Map::Units::UT_S_BALLISTA: - /* - ballista - */ - _entityType = 0x14; break; case OpenSHC::Map::Units::UT_A_SLINGER: - /* - slinger - */ - _entityType = 0x21; break; case OpenSHC::Map::Units::UT_A_FIRETHROWER: - /* - fire thrower - */ - _entityType = 0x22; break; case OpenSHC::Map::Units::UT_S_FBALLISTA: - /* - fire ballista - */ - _entityType = 0x25; } int _rangeSquared = DAT_EntityDefinedData::instance.EntityTypeArrayForProjectileRange[_entityType] @@ -211,15 +171,7 @@ namespace Map { } } } - /* - fixme - */ - sVar9 = this->units[unitID]._someX_2; - /* - fixmefixme - */ - this->units[unitID].targetedUnitID__OR__engineerMannedSiegeEngineRef = 0; this->units[unitID].shootTargetedUnit = 0; this->units[unitID].targetingType = OpenSHC::Map::Units::UIT_NO_INSTRUCTION_OR_MOVEUnk; From 338ee16f1d4b6432a699f664565a84d8bf8c2fbf Mon Sep 17 00:00:00 2001 From: Gynt Date: Mon, 28 Sep 2026 00:35:44 +0200 Subject: [PATCH 259/299] reimplement: SHC_3BB0A8C1_0x0054A7B0 34.28% reg alloc, spill order --- .../Map/Units/UnitsState/findNearestEnemyAndHeadTowardsIt.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/findNearestEnemyAndHeadTowardsIt.cpp b/src/OpenSHC/Map/Units/UnitsState/findNearestEnemyAndHeadTowardsIt.cpp index f4cecf359..e587f0d6e 100644 --- a/src/OpenSHC/Map/Units/UnitsState/findNearestEnemyAndHeadTowardsIt.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/findNearestEnemyAndHeadTowardsIt.cpp @@ -200,7 +200,6 @@ namespace Map { && this->units[_enemyUnitID].unitType != OpenSHC::Map::Units::UT_CAGEDOG) { continue; } - /* unit type switch */ switch (this->units[_enemyUnitID].unitType) { case OpenSHC::Map::Units::UT_PEASANT: _score = _score * 8 + 200; From c68829bb044c9d72479bb0d24580e5a6ba71f537 Mon Sep 17 00:00:00 2001 From: Gynt Date: Mon, 28 Sep 2026 00:35:44 +0200 Subject: [PATCH 260/299] reimplement: SHC_3BB0A8C1_0x00531220 44.04% block order, reg alloc --- src/OpenSHC/Map/Units/UnitsState/processUnitAttackOtherUnit.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/processUnitAttackOtherUnit.cpp b/src/OpenSHC/Map/Units/UnitsState/processUnitAttackOtherUnit.cpp index 458b5abdc..bb7e9cc25 100644 --- a/src/OpenSHC/Map/Units/UnitsState/processUnitAttackOtherUnit.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/processUnitAttackOtherUnit.cpp @@ -28,7 +28,6 @@ namespace Map { undefined4 UnitsState::processUnitAttackOtherUnit(int unitID, int unit2ID) { int _tribeID = this->units[unit2ID].tribeID; - /* get the unit type of unit2 */ UnitTypeShort _unit2Type = this->units[unit2ID].unitType; /* get the damage from the array based: row is unit1ID type, column is unit2ID type */ int _damage = DAT_UnitPropertiesDefinedData::instance From 2f62820b24c409d3c0785e20d316d771f078f94c Mon Sep 17 00:00:00 2001 From: Gynt Date: Mon, 28 Sep 2026 00:35:45 +0200 Subject: [PATCH 261/299] reimplement: SHC_3BB0A8C1_0x0053B8E0 86.89% reg alloc --- src/OpenSHC/Map/Units/UnitsState/setUnitValues.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/setUnitValues.cpp b/src/OpenSHC/Map/Units/UnitsState/setUnitValues.cpp index fe64c4757..d1237fad1 100644 --- a/src/OpenSHC/Map/Units/UnitsState/setUnitValues.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/setUnitValues.cpp @@ -74,7 +74,6 @@ namespace Map { if (unitType != OpenSHC::Map::Units::UT_CAGEDOG) { this->units[unitID].unknownBool01 = 500; } - /* Assassin */ if (unitType == OpenSHC::Map::Units::UT_A_ASSASSIN) { this->units[unitID].assassinsMicroDistanceToEnemyUnk = 32000; } From 643a2e4877103f1fa205f89503a8d0836421a178 Mon Sep 17 00:00:00 2001 From: Gynt Date: Mon, 28 Sep 2026 00:35:45 +0200 Subject: [PATCH 262/299] reimplement: SHC_3BB0A8C1_0x00579300 34.14% reg alloc, dup tails --- src/OpenSHC/Map/Units/UnitsState/updateUnits.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/updateUnits.cpp b/src/OpenSHC/Map/Units/UnitsState/updateUnits.cpp index f6d2abde9..219f36f41 100644 --- a/src/OpenSHC/Map/Units/UnitsState/updateUnits.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/updateUnits.cpp @@ -930,7 +930,6 @@ namespace Map { return; } DAT_UpdateUnitsTracker::instance = DAT_UpdateUnitsTracker::instance + 1; - return; } } From 84bc404dc1e0e4d134dab69531d12fb3b7523fe7 Mon Sep 17 00:00:00 2001 From: Gynt Date: Mon, 28 Sep 2026 01:33:17 +0200 Subject: [PATCH 263/299] reimplement: SHC_3BB0A8C1_0x00536E30 32.30% reg alloc, spill order --- src/OpenSHC/Map/Units/UnitsState/giveMoveCommand.cpp | 6 +++--- status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/giveMoveCommand.cpp b/src/OpenSHC/Map/Units/UnitsState/giveMoveCommand.cpp index 32a196229..9ec50d99a 100644 --- a/src/OpenSHC/Map/Units/UnitsState/giveMoveCommand.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/giveMoveCommand.cpp @@ -37,14 +37,14 @@ namespace Map { UnitType _mostFrequentUnitType = MACRO_CALL_MEMBER(OpenSHC::Map::Units::TribesState_Func::getMajoritySelectedUnitType, DAT_TribesState::ptr)(tribeID, (int*)0x0); - ushort _areaAtDestination + short _areaAtDestination = DAT_TileMapState::instance .PathConnectionLayer[DAT_ViewportRenderState::instance.viewportState.field24_0x60]; uint _logicAtDestination = DAT_TileMapState::instance.LogicLayer[DAT_ViewportRenderState::instance.viewportState.field24_0x60]; int _combatUnitID = MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::selectionContainsCombatUnit, this)(1); - ushort _areaAtUnit = DAT_TileMapState::instance.PathConnectionLayer[this->units[_combatUnitID].tile]; + short _areaAtUnit = DAT_TileMapState::instance.PathConnectionLayer[this->units[_combatUnitID].tile]; if ((DAT_TileMapState::instance.LogicLayer[this->units[_combatUnitID].tile] & 0x40000000U) != 0) { return; } @@ -52,7 +52,7 @@ namespace Map { = MACRO_CALL_MEMBER( OpenSHC::Map::Navigation::PathFindingState_Func::calculateCanPlayerUnitsNavigateToAreaFromArea, DAT_PathFindingState::ptr)(DAT_GameSynchronyState::instance.currentPlayerSlotID, - (short)_areaAtDestination, (short)_areaAtUnit, + _areaAtDestination, _areaAtUnit, MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::canAUnitClimb, this)()) != 0; if (MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::selectionHasMobileAssaultUnits, this)() != 0) { diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index d369f5899..f7f6cf703 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -51217,7 +51217,7 @@ SHC_3BB0A8C1_0x00536DE0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00536E10 | 0.0% | Pending -SHC_3BB0A8C1_0x00536E30 | 24.7% | branch shape differs +SHC_3BB0A8C1_0x00536E30 | 32.3% | reg alloc, spill order SHC_3BB0A8C1_0x00537070 | 86.4% | enum cast, reg alloc From fd1b4c51ef4d9e7efc2caeb10946d1232cd909ec Mon Sep 17 00:00:00 2001 From: Gynt Date: Mon, 28 Sep 2026 09:06:18 +0200 Subject: [PATCH 264/299] reimplement: SHC_3BB0A8C1_0x00533630 24.03% reg alloc --- .../findAndAttackNearbyEnemyLaddermanInPosition.cpp | 5 +++-- status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/findAndAttackNearbyEnemyLaddermanInPosition.cpp b/src/OpenSHC/Map/Units/UnitsState/findAndAttackNearbyEnemyLaddermanInPosition.cpp index 226778808..734eb86cd 100644 --- a/src/OpenSHC/Map/Units/UnitsState/findAndAttackNearbyEnemyLaddermanInPosition.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/findAndAttackNearbyEnemyLaddermanInPosition.cpp @@ -20,11 +20,12 @@ namespace Map { // FUNCTION: STRONGHOLDCRUSADER 0x00533630 BOOLEnum UnitsState::findAndAttackNearbyEnemyLaddermanInPosition(int unitID) { - if ((DAT_TileMapState::instance.LogicLayer[this->units[unitID].tile] & LogicHelpers::L_WALL_OR_GATEHOUSE) == 0) { + if ((DAT_TileMapState::instance.LogicLayer[this->units[unitID].tile] & LogicHelpers::L_WALL_OR_GATEHOUSE) + == 0) { return FALSE; } short _owner = this->units[unitID].owner; - ushort _areaOfUnit = DAT_TileMapState::instance.PathConnectionLayer[this->units[unitID].tile]; + dword _areaOfUnit = (short)DAT_TileMapState::instance.PathConnectionLayer[this->units[unitID].tile]; int _bestEnemyUnitID = 0; int _minDistance = 1000; for (int i = 0; i < DAT_GameState::instance.playerDataArray[_owner].enemies; ++i) { diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index f7f6cf703..3c8511ac0 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -50673,7 +50673,7 @@ SHC_3BB0A8C1_0x005334A0 | 41.2% | orig caches unitType local SHC_3BB0A8C1_0x00533580 | 24.5% | orig caches locals -SHC_3BB0A8C1_0x00533630 | 20.6% | orig walks enemy array ptr +SHC_3BB0A8C1_0x00533630 | 24.0% | reg alloc SHC_3BB0A8C1_0x00533810 | 80.3% | orig walks matrix row ptr From 8f711cf8740065dbda70fd9a64dede00eafbbe62 Mon Sep 17 00:00:00 2001 From: Gynt Date: Mon, 28 Sep 2026 09:06:19 +0200 Subject: [PATCH 265/299] reimplement: SHC_3BB0A8C1_0x00537AA0 40.00% reg alloc --- .../Map/Units/UnitsState/findClosestAnimalStoreResult.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/findClosestAnimalStoreResult.cpp b/src/OpenSHC/Map/Units/UnitsState/findClosestAnimalStoreResult.cpp index 8767098d6..666e1aec3 100644 --- a/src/OpenSHC/Map/Units/UnitsState/findClosestAnimalStoreResult.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/findClosestAnimalStoreResult.cpp @@ -27,8 +27,8 @@ namespace Map { if (DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[y * 400 + x] == 0) { return 0; } - ushort _areaOfOrigin - = DAT_TileMapState::instance + dword _areaOfOrigin + = (short)DAT_TileMapState::instance .PathConnectionLayer[DAT_ViewportRenderState::instance.translationMatrix[y].addXgetTile + x]; this->unusedUnitIDArrayIndex = 0; int _bestScore = 10000; From cbd8aa4e4d92f13ae387411473ae94f46a7f6628 Mon Sep 17 00:00:00 2001 From: Gynt Date: Mon, 28 Sep 2026 09:06:20 +0200 Subject: [PATCH 266/299] reimplement: SHC_3BB0A8C1_0x00537C10 60.36% reg alloc --- .../Map/Units/UnitsState/findClosestEnemyByAreaAndRange.cpp | 4 ++-- status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/findClosestEnemyByAreaAndRange.cpp b/src/OpenSHC/Map/Units/UnitsState/findClosestEnemyByAreaAndRange.cpp index d8ce6bf93..c4f764f49 100644 --- a/src/OpenSHC/Map/Units/UnitsState/findClosestEnemyByAreaAndRange.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/findClosestEnemyByAreaAndRange.cpp @@ -24,8 +24,8 @@ namespace Map { if (DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[y * 400 + x] == 0) { return 0; } - ushort _areaOfOrigin - = DAT_TileMapState::instance + dword _areaOfOrigin + = (short)DAT_TileMapState::instance .PathConnectionLayer[DAT_ViewportRenderState::instance.translationMatrix[y].addXgetTile + x]; this->unusedUnitIDArrayIndex = 0; int _bestScore = 10000; diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 3c8511ac0..0e01a6fce 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -51253,7 +51253,7 @@ SHC_3BB0A8C1_0x00537AA0 | 40.0% | reg alloc SHC_3BB0A8C1_0x00537B20 | 0.0% | Pending -SHC_3BB0A8C1_0x00537C10 | 50.9% | reg alloc +SHC_3BB0A8C1_0x00537C10 | 60.4% | reg alloc SHC_3BB0A8C1_0x00537C90 | 0.0% | Pending From eec09ed6c3cb6d079edbed08e5c28f431ea3e7fd Mon Sep 17 00:00:00 2001 From: Gynt Date: Mon, 28 Sep 2026 09:06:21 +0200 Subject: [PATCH 267/299] reimplement: SHC_3BB0A8C1_0x0054A7B0 34.28% reg alloc, spill order --- .../Map/Units/UnitsState/findNearestEnemyAndHeadTowardsIt.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/findNearestEnemyAndHeadTowardsIt.cpp b/src/OpenSHC/Map/Units/UnitsState/findNearestEnemyAndHeadTowardsIt.cpp index e587f0d6e..4acd19010 100644 --- a/src/OpenSHC/Map/Units/UnitsState/findNearestEnemyAndHeadTowardsIt.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/findNearestEnemyAndHeadTowardsIt.cpp @@ -28,7 +28,7 @@ namespace Map { int _microX = this->units[unitID].microXPosition; int _microY = this->units[unitID].microYPosition; int _playerID = this->units[unitID].owner; - int _area = DAT_TileMapState::instance.PathConnectionLayer[this->units[unitID].tile]; + dword _area = (short)DAT_TileMapState::instance.PathConnectionLayer[this->units[unitID].tile]; this->unitDistanceComputationResultUnk = 100000; dword _minDistance = 100000; dword _chosenRawDistance = 0; From c55cdf8c03a234548f87edcf69da860a45f1b013 Mon Sep 17 00:00:00 2001 From: Gynt Date: Mon, 28 Sep 2026 09:06:21 +0200 Subject: [PATCH 268/299] reimplement: SHC_3BB0A8C1_0x00530650 83.93% reg alloc --- .../UnitsState/makeUnitsDisappearThatCannotReachTheKeep.cpp | 4 ++-- status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/makeUnitsDisappearThatCannotReachTheKeep.cpp b/src/OpenSHC/Map/Units/UnitsState/makeUnitsDisappearThatCannotReachTheKeep.cpp index 98dd92ca9..2b6f6ba63 100644 --- a/src/OpenSHC/Map/Units/UnitsState/makeUnitsDisappearThatCannotReachTheKeep.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/makeUnitsDisappearThatCannotReachTheKeep.cpp @@ -17,8 +17,8 @@ namespace Map { // FUNCTION: STRONGHOLDCRUSADER 0x00530650 void UnitsState::makeUnitsDisappearThatCannotReachTheKeep(int playerID) { - ushort _areaOfKeep - = DAT_TileMapState::instance + dword _areaOfKeep + = (short)DAT_TileMapState::instance .PathConnectionLayer[DAT_GameState::instance.playerDataArray[playerID].campground.tileEntry]; for (int unitID = 1; unitID < (int)this->maxUnitCount; ++unitID) { if (this->units[unitID].owner != playerID) { diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 0e01a6fce..4aa165874 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -49623,7 +49623,7 @@ SHC_3BB0A8C1_0x00530648 | 0.0% | Pending SHC_3BB0A8C1_0x00530649 | 0.0% | Pending -SHC_3BB0A8C1_0x00530650 | 80.4% | reg alloc differs +SHC_3BB0A8C1_0x00530650 | 83.9% | reg alloc SHC_3BB0A8C1_0x00530690 | 0.0% | Pending From 20d852cdca695a957ab1cb10f82fe48bee53be71 Mon Sep 17 00:00:00 2001 From: Gynt Date: Mon, 28 Sep 2026 09:06:22 +0200 Subject: [PATCH 269/299] reimplement: SHC_3BB0A8C1_0x0053DCC0 25.37% reg alloc --- .../Map/Units/UnitsState/setDestinationNearTargetedBuilding.cpp | 2 +- status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/setDestinationNearTargetedBuilding.cpp b/src/OpenSHC/Map/Units/UnitsState/setDestinationNearTargetedBuilding.cpp index b71d1b87e..0f3239aab 100644 --- a/src/OpenSHC/Map/Units/UnitsState/setDestinationNearTargetedBuilding.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/setDestinationNearTargetedBuilding.cpp @@ -17,7 +17,7 @@ namespace Map { // FUNCTION: STRONGHOLDCRUSADER 0x0053DCC0 undefined4 UnitsState::setDestinationNearTargetedBuilding(int unitID, int param_2) { - ushort _areaAtUnitTile = DAT_TileMapState::instance.PathConnectionLayer[this->units[unitID].tile]; + dword _areaAtUnitTile = (short)DAT_TileMapState::instance.PathConnectionLayer[this->units[unitID].tile]; DAT_TileMapState::instance.PathConnectionLayer[this->units[unitID].targetedBuildingTile] = _areaAtUnitTile; MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func:: findFreeSpaceNextToEnemyDefensiveStructureInSameAreaWithinDistance, diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 4aa165874..a7235b9fe 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -60035,7 +60035,7 @@ SHC_3BB0A8C1_0x0053DCB0 | 0.0% | Pending SHC_3BB0A8C1_0x0053DCB4 | 0.0% | Pending -SHC_3BB0A8C1_0x0053DCC0 | 14.9% | orig caches many locals +SHC_3BB0A8C1_0x0053DCC0 | 25.4% | reg alloc SHC_3BB0A8C1_0x0053DDD0 | 65.5% | orig unrolls scan loop x4 From 9032434b2020edf9d8e102da11c34a626e905c05 Mon Sep 17 00:00:00 2001 From: Gynt Date: Mon, 28 Sep 2026 09:06:23 +0200 Subject: [PATCH 270/299] reimplement: SHC_3BB0A8C1_0x00536E30 34.48% reg alloc, spill order --- src/OpenSHC/Map/Units/UnitsState/giveMoveCommand.cpp | 6 +++--- status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/giveMoveCommand.cpp b/src/OpenSHC/Map/Units/UnitsState/giveMoveCommand.cpp index 9ec50d99a..6e98851cb 100644 --- a/src/OpenSHC/Map/Units/UnitsState/giveMoveCommand.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/giveMoveCommand.cpp @@ -37,14 +37,14 @@ namespace Map { UnitType _mostFrequentUnitType = MACRO_CALL_MEMBER(OpenSHC::Map::Units::TribesState_Func::getMajoritySelectedUnitType, DAT_TribesState::ptr)(tribeID, (int*)0x0); - short _areaAtDestination - = DAT_TileMapState::instance + dword _areaAtDestination + = (short)DAT_TileMapState::instance .PathConnectionLayer[DAT_ViewportRenderState::instance.viewportState.field24_0x60]; uint _logicAtDestination = DAT_TileMapState::instance.LogicLayer[DAT_ViewportRenderState::instance.viewportState.field24_0x60]; int _combatUnitID = MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::selectionContainsCombatUnit, this)(1); - short _areaAtUnit = DAT_TileMapState::instance.PathConnectionLayer[this->units[_combatUnitID].tile]; + dword _areaAtUnit = (short)DAT_TileMapState::instance.PathConnectionLayer[this->units[_combatUnitID].tile]; if ((DAT_TileMapState::instance.LogicLayer[this->units[_combatUnitID].tile] & 0x40000000U) != 0) { return; } diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index a7235b9fe..265cb997a 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -51217,7 +51217,7 @@ SHC_3BB0A8C1_0x00536DE0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00536E10 | 0.0% | Pending -SHC_3BB0A8C1_0x00536E30 | 32.3% | reg alloc, spill order +SHC_3BB0A8C1_0x00536E30 | 34.5% | reg alloc, spill order SHC_3BB0A8C1_0x00537070 | 86.4% | enum cast, reg alloc From 852d5c5938ab3d828bf138b7607af41c112da6c8 Mon Sep 17 00:00:00 2001 From: Gynt Date: Mon, 28 Sep 2026 10:06:17 +0200 Subject: [PATCH 271/299] reimplement: SHC_3BB0A8C1_0x0053D3D0 36.15% reg alloc, spill order --- .../Units/UnitsState/setDestinationForUnit.cpp | 16 +++++++--------- status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/setDestinationForUnit.cpp b/src/OpenSHC/Map/Units/UnitsState/setDestinationForUnit.cpp index 5654c9353..d1eb1a4bf 100644 --- a/src/OpenSHC/Map/Units/UnitsState/setDestinationForUnit.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/setDestinationForUnit.cpp @@ -21,8 +21,7 @@ namespace Map { /* check by unit type */ int _ableToClimbTowers = DAT_UnitPropertiesDefinedData::instance.ABLE_TO_CLIMB_TOWERS[(short)this->units[unitID].unitType]; - if (x > 399 || y > 399 - || DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[y * 400 + x] == 0) { + if (x > 399 || y > 399 || DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[y * 400 + x] == 0) { DAT_PathFindingState::instance.allAssassinsUnk = 0; return FALSE; } @@ -30,31 +29,30 @@ namespace Map { if (MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::unitIsInMoat, this)(unitID) != FALSE) { DAT_PathFindingState::instance.climbIsIllegal = 1; } + uint _unitX = this->units[unitID].x; this->units[unitID].climbDataID = 0; this->units[unitID].destinationX_2Unk = (short)x; this->units[unitID].destinationY_2Unk = (short)y; this->units[unitID].field280_0x3f4 = 0; - if (this->units[unitID].x == x && this->units[unitID].y == y) { + if (_unitX == x && this->units[unitID].y == y) { this->units[unitID].destinationYPosition = (short)y; this->units[unitID].totalSizeOfPathPlan = 0; this->units[unitID].tunnelerFinishedDigging = 0; this->units[unitID].currentIndexInPathPlan = 0; this->units[unitID].destinationXPosition = (short)x; - this->units[unitID].ladderExitXPosition = this->units[unitID].x; + this->units[unitID].ladderExitXPosition = (short)_unitX; this->units[unitID].ladderExitYPosition = this->units[unitID].y; this->units[unitID].destinationTilePosition = (short)x + DAT_ViewportRenderState::instance.translationMatrix[(short)y].addXgetTile; this->units[unitID].previousTilePosition - = DAT_ViewportRenderState::instance.translationMatrix[this->units[unitID].y].addXgetTile - + this->units[unitID].x; + = DAT_ViewportRenderState::instance.translationMatrix[y].addXgetTile + _unitX; DAT_PathFindingState::instance.climbIsIllegal = 0; DAT_PathFindingState::instance.allAssassinsUnk = 0; return TRUE; } dword _fromArea = (short)DAT_TileMapState::instance.PathConnectionLayer - [DAT_ViewportRenderState::instance.translationMatrix[this->units[unitID].y].addXgetTile - + this->units[unitID].x]; + [DAT_ViewportRenderState::instance.translationMatrix[this->units[unitID].y].addXgetTile + _unitX]; int _destinationTile = DAT_ViewportRenderState::instance.translationMatrix[y].addXgetTile + x; dword _toArea = (short)DAT_TileMapState::instance.PathConnectionLayer[_destinationTile]; if ((DAT_TileMapState::instance.LogicLayer[_destinationTile] & 0x30) != 0) { @@ -199,7 +197,7 @@ namespace Map { this->units[unitID].ladderExitYPosition = this->units[unitID].y; this->units[unitID].destinationTilePosition = (short)_pathTargetX + DAT_ViewportRenderState::instance.translationMatrix[(short)_pathTargetY].addXgetTile; - this->units[unitID].ladderExitXPosition = this->units[unitID].x; + this->units[unitID].ladderExitXPosition = (short)_unitX; this->units[unitID].previousTilePosition = this->units[unitID].x + DAT_ViewportRenderState::instance.translationMatrix[this->units[unitID].y].addXgetTile; this->units[unitID].cannotClimb = (ushort)(DAT_PathFindingState::instance.climbIsIllegal != 0); diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 265cb997a..cca54b08a 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -60013,7 +60013,7 @@ SHC_3BB0A8C1_0x0053D3C1 | 0.0% | Pending SHC_3BB0A8C1_0x0053D3C2 | 0.0% | Pending -SHC_3BB0A8C1_0x0053D3D0 | 28.2% | reg alloc, spill order +SHC_3BB0A8C1_0x0053D3D0 | 36.1% | reg alloc, spill order SHC_3BB0A8C1_0x0053D850 | 69.8% | reg alloc differs From 92d8971d3b3b6f76d36a1b50f71a88d8a1484731 Mon Sep 17 00:00:00 2001 From: Gynt Date: Mon, 28 Sep 2026 10:36:54 +0200 Subject: [PATCH 272/299] reimplement: SHC_3BB0A8C1_0x00533630 42.29% reg alloc --- ...ndAttackNearbyEnemyLaddermanInPosition.cpp | 24 ++++++++++--------- status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/findAndAttackNearbyEnemyLaddermanInPosition.cpp b/src/OpenSHC/Map/Units/UnitsState/findAndAttackNearbyEnemyLaddermanInPosition.cpp index 734eb86cd..fe7aa48f1 100644 --- a/src/OpenSHC/Map/Units/UnitsState/findAndAttackNearbyEnemyLaddermanInPosition.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/findAndAttackNearbyEnemyLaddermanInPosition.cpp @@ -20,14 +20,16 @@ namespace Map { // FUNCTION: STRONGHOLDCRUSADER 0x00533630 BOOLEnum UnitsState::findAndAttackNearbyEnemyLaddermanInPosition(int unitID) { - if ((DAT_TileMapState::instance.LogicLayer[this->units[unitID].tile] & LogicHelpers::L_WALL_OR_GATEHOUSE) - == 0) { - return FALSE; - } + int _unitX = this->units[unitID].x; short _owner = this->units[unitID].owner; - dword _areaOfUnit = (short)DAT_TileMapState::instance.PathConnectionLayer[this->units[unitID].tile]; + int _unitY = this->units[unitID].y; + int _tile = this->units[unitID].tile; + dword _areaOfUnit = (short)DAT_TileMapState::instance.PathConnectionLayer[_tile]; int _bestEnemyUnitID = 0; int _minDistance = 1000; + if ((DAT_TileMapState::instance.LogicLayer[_tile] & LogicHelpers::L_WALL_OR_GATEHOUSE) == 0) { + return FALSE; + } for (int i = 0; i < DAT_GameState::instance.playerDataArray[_owner].enemies; ++i) { int _enemyUnitID = DAT_GameState::instance.playerDataArray[_owner].enemyIDArray[i]; if (this->units[_enemyUnitID].unitType != OpenSHC::Map::Units::UT_E_LADDER) { @@ -45,16 +47,16 @@ namespace Map { DAT_PathFindingState::ptr)( (short)_areaOfUnit, this->units[_enemyUnitID].x, this->units[_enemyUnitID].y); int _distanceX; - if (DAT_PathFindingState::instance.climbX < this->units[unitID].x) { - _distanceX = this->units[unitID].x - DAT_PathFindingState::instance.climbX; + if (DAT_PathFindingState::instance.climbX < _unitX) { + _distanceX = _unitX - DAT_PathFindingState::instance.climbX; } else { - _distanceX = DAT_PathFindingState::instance.climbX - this->units[unitID].x; + _distanceX = DAT_PathFindingState::instance.climbX - _unitX; } int _distanceY; - if (DAT_PathFindingState::instance.climbY < this->units[unitID].y) { - _distanceY = this->units[unitID].y - DAT_PathFindingState::instance.climbY; + if (DAT_PathFindingState::instance.climbY < _unitY) { + _distanceY = _unitY - DAT_PathFindingState::instance.climbY; } else { - _distanceY = DAT_PathFindingState::instance.climbY - this->units[unitID].y; + _distanceY = DAT_PathFindingState::instance.climbY - _unitY; } if (_distanceX < _distanceY) { /* stores the largest distance into _distanceX */ diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index cca54b08a..39e9f23e7 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -50673,7 +50673,7 @@ SHC_3BB0A8C1_0x005334A0 | 41.2% | orig caches unitType local SHC_3BB0A8C1_0x00533580 | 24.5% | orig caches locals -SHC_3BB0A8C1_0x00533630 | 24.0% | reg alloc +SHC_3BB0A8C1_0x00533630 | 42.3% | reg alloc SHC_3BB0A8C1_0x00533810 | 80.3% | orig walks matrix row ptr From 949a68220b4f8a45aec946c1be007351a7a7c0c0 Mon Sep 17 00:00:00 2001 From: Gynt Date: Mon, 28 Sep 2026 10:42:47 +0200 Subject: [PATCH 273/299] reimplement: SHC_3BB0A8C1_0x00531000 38.28% reg alloc, branch order --- .../UnitsState/shouldUnitsEngageInMelee.cpp | 61 +++++++++---------- status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 30 insertions(+), 33 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/shouldUnitsEngageInMelee.cpp b/src/OpenSHC/Map/Units/UnitsState/shouldUnitsEngageInMelee.cpp index 9e891e0b6..ba003c191 100644 --- a/src/OpenSHC/Map/Units/UnitsState/shouldUnitsEngageInMelee.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/shouldUnitsEngageInMelee.cpp @@ -17,48 +17,45 @@ namespace Map { // FUNCTION: STRONGHOLDCRUSADER 0x00531000 BOOLEnum UnitsState::shouldUnitsEngageInMelee(int unitID_1, int unitID_2) { - if (this->units[unitID_1].unitType == OpenSHC::Map::Units::UT_TRADER - || this->units[unitID_1].unitType == OpenSHC::Map::Units::UT_TRADERHORSE) { + UnitTypeShort _type1 = this->units[unitID_1].unitType; + if (_type1 == OpenSHC::Map::Units::UT_TRADER || _type1 == OpenSHC::Map::Units::UT_TRADERHORSE) { return TRUE; } - if (this->units[unitID_2].unitType == OpenSHC::Map::Units::UT_TRADER - || this->units[unitID_2].unitType == OpenSHC::Map::Units::UT_TRADERHORSE - || this->units[unitID_1].unitType == OpenSHC::Map::Units::UT_GHOST - || this->units[unitID_2].unitType == OpenSHC::Map::Units::UT_GHOST) { + UnitTypeShort _type2 = this->units[unitID_2].unitType; + if (_type2 == OpenSHC::Map::Units::UT_TRADER || _type2 == OpenSHC::Map::Units::UT_TRADERHORSE + || _type1 == OpenSHC::Map::Units::UT_GHOST || _type2 == OpenSHC::Map::Units::UT_GHOST) { return TRUE; } - if (this->units[unitID_1].unitType == OpenSHC::Map::Units::UT_CAMELSHBEAR) { - if (this->units[unitID_2].unitType == OpenSHC::Map::Units::UT_WOODCUTTER) { + if (_type1 == OpenSHC::Map::Units::UT_CAMELSHBEAR) { + if (_type2 == OpenSHC::Map::Units::UT_WOODCUTTER) { return FALSE; } - if (this->units[unitID_2].unitType == OpenSHC::Map::Units::UT_LIONSHWOLF) { + if (_type2 == OpenSHC::Map::Units::UT_LIONSHWOLF) { return FALSE; } return TRUE; } - if (this->units[unitID_2].unitType == OpenSHC::Map::Units::UT_CAMELSHBEAR) { - if (this->units[unitID_1].unitType == OpenSHC::Map::Units::UT_WOODCUTTER - || this->units[unitID_1].unitType == OpenSHC::Map::Units::UT_LIONSHWOLF) { + if (_type2 == OpenSHC::Map::Units::UT_CAMELSHBEAR) { + if (_type1 == OpenSHC::Map::Units::UT_WOODCUTTER || _type1 == OpenSHC::Map::Units::UT_LIONSHWOLF) { return FALSE; } return TRUE; } if (this->units[unitID_1].isStalked == 0) { if (this->units[unitID_2].isStalked != 0) { - if (this->units[unitID_2].unitType == OpenSHC::Map::Units::UT_LIONSHWOLF) { + if (_type2 == OpenSHC::Map::Units::UT_LIONSHWOLF) { return FALSE; } - if (this->units[unitID_2].unitType == OpenSHC::Map::Units::UT_CAGEDOG) { + if (_type2 == OpenSHC::Map::Units::UT_CAGEDOG) { return (BOOLEnum)(DAT_GameState::instance.mapAndTime .playerTeams[this->units[unitID_2].displayColorPlayerID] == DAT_GameState::instance.mapAndTime.playerTeams[this->units[unitID_1].owner]); } - if (this->units[unitID_2].unitType == OpenSHC::Map::Units::UT_RABBIT - || this->units[unitID_2].unitType == OpenSHC::Map::Units::UT_QUARRYOX - || this->units[unitID_2].unitType == OpenSHC::Map::Units::UT_COW) { + if (_type2 == OpenSHC::Map::Units::UT_RABBIT || _type2 == OpenSHC::Map::Units::UT_QUARRYOX + || _type2 == OpenSHC::Map::Units::UT_COW) { return FALSE; } - return (BOOLEnum)(this->units[unitID_2].unitType != OpenSHC::Map::Units::UT_HUNTERDOG); + return (BOOLEnum)(_type2 != OpenSHC::Map::Units::UT_HUNTERDOG); } if (DAT_GameState::instance.mapAndTime.skirmishNoRushTicks == 0 || DAT_GameSynchronyState::instance.currentGameMode == OpenSHC::Game::GM_SKIRMISH_SINGLE_PLAYER @@ -67,30 +64,30 @@ namespace Map { } return TRUE; } - if (this->units[unitID_1].unitType == OpenSHC::Map::Units::UT_LIONSHWOLF) { - if (this->units[unitID_2].unitType == OpenSHC::Map::Units::UT_ANTELOPESHDEER) { + if (_type1 == OpenSHC::Map::Units::UT_LIONSHWOLF) { + if (_type2 == OpenSHC::Map::Units::UT_ANTELOPESHDEER) { return FALSE; } - if (this->units[unitID_2].unitType == OpenSHC::Map::Units::UT_COW) { + if (_type2 == OpenSHC::Map::Units::UT_COW) { return FALSE; } - if (this->units[unitID_2].unitType == OpenSHC::Map::Units::UT_RABBIT) { + if (_type2 == OpenSHC::Map::Units::UT_RABBIT) { return FALSE; } - if (this->units[unitID_2].unitType == OpenSHC::Map::Units::UT_HUNTERDOG) { + if (_type2 == OpenSHC::Map::Units::UT_HUNTERDOG) { return FALSE; } - } else if (this->units[unitID_1].unitType == OpenSHC::Map::Units::UT_CAGEDOG) { - if (this->units[unitID_2].unitType == OpenSHC::Map::Units::UT_ANTELOPESHDEER) { + } else if (_type1 == OpenSHC::Map::Units::UT_CAGEDOG) { + if (_type2 == OpenSHC::Map::Units::UT_ANTELOPESHDEER) { return FALSE; } - if (this->units[unitID_2].unitType == OpenSHC::Map::Units::UT_COW) { + if (_type2 == OpenSHC::Map::Units::UT_COW) { return FALSE; } - if (this->units[unitID_2].unitType == OpenSHC::Map::Units::UT_RABBIT) { + if (_type2 == OpenSHC::Map::Units::UT_RABBIT) { return FALSE; } - if (this->units[unitID_2].unitType == OpenSHC::Map::Units::UT_HUNTERDOG) { + if (_type2 == OpenSHC::Map::Units::UT_HUNTERDOG) { return FALSE; } if (this->units[unitID_2].isStalked != 0) { @@ -99,16 +96,16 @@ namespace Map { return ( BOOLEnum)(DAT_GameState::instance.mapAndTime.playerTeams[this->units[unitID_1].displayColorPlayerID] == DAT_GameState::instance.mapAndTime.playerTeams[this->units[unitID_2].owner]); - } else if (this->units[unitID_1].unitType != OpenSHC::Map::Units::UT_HUNTERDOG) { + } else if (_type1 != OpenSHC::Map::Units::UT_HUNTERDOG) { return TRUE; } else { - if (this->units[unitID_2].unitType == OpenSHC::Map::Units::UT_RABBIT) { + if (_type2 == OpenSHC::Map::Units::UT_RABBIT) { return FALSE; } - if (this->units[unitID_2].unitType == OpenSHC::Map::Units::UT_LIONSHWOLF) { + if (_type2 == OpenSHC::Map::Units::UT_LIONSHWOLF) { return FALSE; } - if (this->units[unitID_2].unitType == OpenSHC::Map::Units::UT_CAGEDOG) { + if (_type2 == OpenSHC::Map::Units::UT_CAGEDOG) { return FALSE; } } diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 39e9f23e7..c5a3dcf80 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -49661,7 +49661,7 @@ SHC_3BB0A8C1_0x00530F20 | 0.0% | Pending SHC_3BB0A8C1_0x00530FD0 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x00531000 | 38.3% | orig caches unitTypes local +SHC_3BB0A8C1_0x00531000 | 38.3% | reg alloc, branch order SHC_3BB0A8C1_0x005311F0 | 100.0% | Reimplemented From ac1f930744ca0f20aece7ec30025049fae3e6b47 Mon Sep 17 00:00:00 2001 From: Gynt Date: Mon, 28 Sep 2026 11:00:35 +0200 Subject: [PATCH 274/299] reimplement: SHC_3BB0A8C1_0x00532BA0 50.28% reg alloc --- .../UnitsState/recomputeTroopValuesForPlayer.cpp | 15 ++++++++------- status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/recomputeTroopValuesForPlayer.cpp b/src/OpenSHC/Map/Units/UnitsState/recomputeTroopValuesForPlayer.cpp index c82c58e2b..3341b63ff 100644 --- a/src/OpenSHC/Map/Units/UnitsState/recomputeTroopValuesForPlayer.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/recomputeTroopValuesForPlayer.cpp @@ -122,15 +122,16 @@ namespace Map { DAT_GameState::instance.playerDataArray[playerID].totalEnemyTroopValue += MACRO_CALL_MEMBER(OpenSHC::Map::Units::TroopValueState_Func::getValueOfTroopType, DAT_TroopValueState::ptr)((UnitType)(short)this->units[unitID].unitType); - if (this->units[unitID].unitType != OpenSHC::Map::Units::UT_E_ARCHER - && this->units[unitID].unitType != OpenSHC::Map::Units::UT_E_XBOW - && this->units[unitID].unitType != OpenSHC::Map::Units::UT_A_ARCHER - && this->units[unitID].unitType != OpenSHC::Map::Units::UT_A_SLINGER - && this->units[unitID].unitType != OpenSHC::Map::Units::UT_A_HARCHER - && this->units[unitID].unitType != OpenSHC::Map::Units::UT_A_FIRETHROWER) { + UnitTypeShort _enemyUnitType = this->units[unitID].unitType; + if (_enemyUnitType != OpenSHC::Map::Units::UT_E_ARCHER + && _enemyUnitType != OpenSHC::Map::Units::UT_E_XBOW + && _enemyUnitType != OpenSHC::Map::Units::UT_A_ARCHER + && _enemyUnitType != OpenSHC::Map::Units::UT_A_SLINGER + && _enemyUnitType != OpenSHC::Map::Units::UT_A_HARCHER + && _enemyUnitType != OpenSHC::Map::Units::UT_A_FIRETHROWER) { DAT_GameState::instance.playerDataArray[playerID].totalEnemyRangedTroopValue += MACRO_CALL_MEMBER(OpenSHC::Map::Units::TroopValueState_Func::getValueOfTroopType, - DAT_TroopValueState::ptr)((UnitType)(short)this->units[unitID].unitType); + DAT_TroopValueState::ptr)((UnitType)(short)_enemyUnitType); } } } diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index c5a3dcf80..4dee18f09 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -50509,7 +50509,7 @@ SHC_3BB0A8C1_0x00532B98 | 0.0% | Pending SHC_3BB0A8C1_0x00532B9C | 0.0% | Pending -SHC_3BB0A8C1_0x00532BA0 | 44.4% | orig walks unit ptr +SHC_3BB0A8C1_0x00532BA0 | 50.3% | reg alloc SHC_3BB0A8C1_0x00532F10 | 0.0% | Pending From 3b0d0dba082bb017ef0bbda6cf727afb4be0f2c4 Mon Sep 17 00:00:00 2001 From: Gynt Date: Mon, 28 Sep 2026 11:09:36 +0200 Subject: [PATCH 275/299] reimplement: SHC_3BB0A8C1_0x0053CBD0 42.49% reg alloc, spill order --- .../UnitsState/prepareProjectileTarget.cpp | 48 +++++++++---------- status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 23 insertions(+), 27 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/prepareProjectileTarget.cpp b/src/OpenSHC/Map/Units/UnitsState/prepareProjectileTarget.cpp index 14fccd1b7..3878c4953 100644 --- a/src/OpenSHC/Map/Units/UnitsState/prepareProjectileTarget.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/prepareProjectileTarget.cpp @@ -35,42 +35,35 @@ namespace Map { } else { _adjustment = (short)((_lead + (_lead >> 0x1f & 7U)) >> 3); } - switch (this->units[targetID].facingDirection) { - case 0: + short _targetFacing = this->units[targetID].facingDirection; + if (_targetFacing == 0) { this->units[shooterID].shootTargetMicroY = this->units[shooterID].shootTargetMicroY - _adjustment; - break; - case 1: + } else if (_targetFacing == 1) { this->units[shooterID].shootTargetMicroY = this->units[shooterID].shootTargetMicroY - _adjustment; this->units[shooterID].shootTargetMicroX = this->units[shooterID].shootTargetMicroX + _adjustment; - break; - case 2: + } else if (_targetFacing == 2) { this->units[shooterID].shootTargetMicroX = this->units[shooterID].shootTargetMicroX + _adjustment; - break; - case 3: + } else if (_targetFacing == 3) { this->units[shooterID].shootTargetMicroY = this->units[shooterID].shootTargetMicroY + _adjustment; this->units[shooterID].shootTargetMicroX = this->units[shooterID].shootTargetMicroX + _adjustment; - break; - case 4: + } else if (_targetFacing == 4) { this->units[shooterID].shootTargetMicroY = this->units[shooterID].shootTargetMicroY + _adjustment; - break; - case 5: + } else if (_targetFacing == 5) { this->units[shooterID].shootTargetMicroY = this->units[shooterID].shootTargetMicroY + _adjustment; this->units[shooterID].shootTargetMicroX = this->units[shooterID].shootTargetMicroX - _adjustment; - break; - case 6: + } else if (_targetFacing == 6) { this->units[shooterID].shootTargetMicroX = this->units[shooterID].shootTargetMicroX - _adjustment; - break; - case 7: + } else if (_targetFacing == 7) { this->units[shooterID].shootTargetMicroY = this->units[shooterID].shootTargetMicroY - _adjustment; this->units[shooterID].shootTargetMicroX @@ -78,7 +71,10 @@ namespace Map { } } } - int _result = (short)this->units[shooterID].unitType + -0x16; + /* the original returns whatever the switch below left in the return register on + the paths that adjust nothing, which is the type's index into it; the value is + not a meaningful result, but callers of those paths are given it */ + int _unhandledTypeResult = (short)this->units[shooterID].unitType + -0x16; int _scatter; if (this->units[shooterID].shootTargetZ < this->units[shooterID].terrainOrClimbHeight) { switch (this->units[shooterID].unitType) { @@ -96,7 +92,7 @@ namespace Map { _scatter = 10; break; default: - return _result; + return _unhandledTypeResult; } } else { _scatter = this->units[shooterID].shootTargetZ - this->units[shooterID].terrainOrClimbHeight; @@ -115,10 +111,10 @@ namespace Map { _scatter = _scatter + 0x46; break; case OpenSHC::Map::Units::UT_S_FBALLISTA: - return _result; + return _unhandledTypeResult; } if (_scatter <= 0) { - return _result; + return _unhandledTypeResult; } if (_scatter > 0x118) { _scatter = 0x118; @@ -126,9 +122,9 @@ namespace Map { } uint _rng = SEC_RNG::instance.currentNumber2; MACRO_CALL_MEMBER(OpenSHC::Random::RNG_Func::nextRandomNumber2, SEC_RNG::ptr)(); - _result = ((int)_rng / 300) * 300; + _unhandledTypeResult = ((int)_rng / 300) * 300; if ((int)_rng % 300 >= _scatter) { - return _result; + return _unhandledTypeResult; } if ((_rng & 7) < 2) { _scatter = (_scatter + (_scatter >> 0x1f & 3U)) >> 2; @@ -161,12 +157,12 @@ namespace Map { } int _heightOffset = _heightRng % _scatter + 0x14; if (_heightRng % _scatter + 0x1c <= (int)this->units[shooterID].shootTargetZ) { - _result = (ushort)this->units[shooterID].shootTargetZ - _heightOffset; + _unhandledTypeResult = (ushort)this->units[shooterID].shootTargetZ - _heightOffset; } else { - _result = (ushort)this->units[shooterID].shootTargetZ + _heightOffset; + _unhandledTypeResult = (ushort)this->units[shooterID].shootTargetZ + _heightOffset; } - this->units[shooterID].shootTargetZ = (short)_result; - return _result; + this->units[shooterID].shootTargetZ = (short)_unhandledTypeResult; + return _unhandledTypeResult; } _scatter = _scatter / 6; if (_scatter == 0) { diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 4dee18f09..727b8c92f 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -59673,7 +59673,7 @@ SHC_3BB0A8C1_0x0053CAC0 | 0.0% | Pending SHC_3BB0A8C1_0x0053CAE0 | 48.6% | reg alloc -SHC_3BB0A8C1_0x0053CBD0 | 37.2% | reg alloc +SHC_3BB0A8C1_0x0053CBD0 | 42.5% | reg alloc, spill order SHC_3BB0A8C1_0x0053CF84 | 0.0% | Pending From 82e7449369910804000ca4199ed834c23bcf9272 Mon Sep 17 00:00:00 2001 From: Gynt Date: Mon, 28 Sep 2026 11:40:52 +0200 Subject: [PATCH 276/299] reimplement: SHC_3BB0A8C1_0x00579300 35.22% reg alloc, dup tails --- .../Map/Units/UnitsState/updateUnits.cpp | 21 ++++++++++++------- status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/updateUnits.cpp b/src/OpenSHC/Map/Units/UnitsState/updateUnits.cpp index 219f36f41..39acfbdc6 100644 --- a/src/OpenSHC/Map/Units/UnitsState/updateUnits.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/updateUnits.cpp @@ -510,24 +510,31 @@ namespace Map { DAT_CurrentUnitSlotID::instance = 1; if (1 < (int)this->maxUnitCount) { do { + bool _updateAnimation = false; switch (this->units[DAT_CurrentUnitSlotID::instance].logicalState) { case OpenSHC::Map::Units::ULS_INVISIBLE: break; + case ((UnitLogicState)1): + this->units[DAT_CurrentUnitSlotID::instance].logicalState = OpenSHC::Map::Units::ULS_NORMAL; + _updateAnimation = true; + break; case OpenSHC::Map::Units::ULS_REMOVE: MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::deleteUnit, this)( DAT_CurrentUnitSlotID::instance); break; + case OpenSHC::Map::Units::ULS_TRANSITIONING: + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::changeUnitType, this)( + DAT_CurrentUnitSlotID::instance); + _updateAnimation = true; + break; case ((UnitLogicState)5): this->units[DAT_CurrentUnitSlotID::instance].logicalState = ((UnitLogicState)1); break; default: - if (this->units[DAT_CurrentUnitSlotID::instance].logicalState - == OpenSHC::Map::Units::ULS_TRANSITIONING) { - MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::changeUnitType, this)( - DAT_CurrentUnitSlotID::instance); - } else if (this->units[DAT_CurrentUnitSlotID::instance].logicalState == (UnitLogicState)1) { - this->units[DAT_CurrentUnitSlotID::instance].logicalState = OpenSHC::Map::Units::ULS_NORMAL; - } + _updateAnimation = true; + break; + } + if (_updateAnimation) { int* _ptr_animationTicker = &this->units[DAT_CurrentUnitSlotID::instance].animationTicker; *_ptr_animationTicker = *_ptr_animationTicker + 1; int _animationTicker = this->units[DAT_CurrentUnitSlotID::instance].animationTicker; diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 727b8c92f..4bb213948 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -66991,7 +66991,7 @@ SHC_3BB0A8C1_0x005792F8 | 0.0% | Pending SHC_3BB0A8C1_0x005792FC | 0.0% | Pending -SHC_3BB0A8C1_0x00579300 | 34.1% | reg alloc, dup tails +SHC_3BB0A8C1_0x00579300 | 35.2% | reg alloc, dup tails SHC_3BB0A8C1_0x00579380 | 0.0% | Pending From 819062cc401bbe911a0f395d66ef59512c3bb281 Mon Sep 17 00:00:00 2001 From: Gynt Date: Mon, 28 Sep 2026 12:01:36 +0200 Subject: [PATCH 277/299] reimplement: SHC_3BB0A8C1_0x00531920 28.71% extra spills, frame size --- .../UnitsState/processEntityDamageToUnit.cpp | 18 +++++++++--------- status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/processEntityDamageToUnit.cpp b/src/OpenSHC/Map/Units/UnitsState/processEntityDamageToUnit.cpp index 6cb7ac477..257fd05e5 100644 --- a/src/OpenSHC/Map/Units/UnitsState/processEntityDamageToUnit.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/processEntityDamageToUnit.cpp @@ -120,7 +120,7 @@ namespace Map { if (tileDistance == 0) { _cowDiseaseDamage = 400; } else { - _cowDiseaseDamage = (-(uint)(tileDistance != 1) & 0xffffffce) + 200; + _cowDiseaseDamage = tileDistance == 1 ? 200 : 150; } int _healerCount = DAT_GameState::instance.playerDataArray[this->units[unitID].owner].healerCount; if (_healerCount >= 3) { @@ -149,7 +149,7 @@ namespace Map { return FALSE; } if (_unitType == OpenSHC::Map::Units::UT_S_TREBUCHET) { - _unitHeight = (-(uint)(tileDistance != 0) & 0xffffffd8) + 0x50; + _unitHeight = tileDistance == 0 ? 0x50 : 0x28; _unitIsSiegeEngine = 1; } else if (_unitType == OpenSHC::Map::Units::UT_S_TOWER) { _unitHeight = 0x50; @@ -223,7 +223,7 @@ namespace Map { if (_entityType_2 == OpenSHC::Map::Units::UT_LORD) { _damage = 0x32; } else { - uVar5 = -(uint)(_entityType_2 != OpenSHC::Map::Units::UT_S_SHIELD) & 0x1c2; + uVar5 = _entityType_2 == OpenSHC::Map::Units::UT_S_SHIELD ? 0 : 0x1c2; } } else if (_entityType == OpenSHC::Map::Entities::ET_MANGONEL) { /* @@ -248,11 +248,11 @@ namespace Map { } else if (_entityType_2 == OpenSHC::Map::Units::UT_S_BATTERINGRAM) { _damage = 10000; } else { - _damage = (-(uint)(_entityType_2 != OpenSHC::Map::Units::UT_S_TOWER) & 20000) + 10000; + _damage = _entityType_2 == OpenSHC::Map::Units::UT_S_TOWER ? 10000 : 30000; } } else { if (_entityType != OpenSHC::Map::Entities::ET_BALLISTA) { - uVar5 = -(uint)(this->units[unitID].unitType != OpenSHC::Map::Units::UT_LORD) & 0x74fe; + uVar5 = this->units[unitID].unitType == OpenSHC::Map::Units::UT_LORD ? 0 : 0x74fe; _damage = uVar5 + 0x32; } /* @@ -281,7 +281,7 @@ namespace Map { 10000 if not siege tower else 20000 */ - _damage = (-(uint)(_targetUnitType != OpenSHC::Map::Units::UT_S_TOWER) & 0xffffd8f0) + 20000; + _damage = _targetUnitType == OpenSHC::Map::Units::UT_S_TOWER ? 20000 : 10000; } if (DAT_EntityState::instance.entityArray[entityID].field90_0xd0 != 0) { /* @@ -387,9 +387,9 @@ namespace Map { if (_entityType == OpenSHC::Map::Entities::ET_COW_FLYING) { this->units[unitID].state.generic = OpenSHC::Map::Units::States::US_STONE_DEATH_01; } else { - this->units[unitID].state.generic - = (-(ushort)(_entityType != OpenSHC::Map::Entities::ET_SLINGER) & 0xfffd) - + OpenSHC::Map::Units::States::US_STONE_DEATH_01; + this->units[unitID].state.generic = _entityType == OpenSHC::Map::Entities::ET_SLINGER + ? OpenSHC::Map::Units::States::US_STONE_DEATH_01 + : (UnitState)(OpenSHC::Map::Units::States::US_STONE_DEATH_01 - 3); } byte bVar2 = this->units[unitID].isStalked; this->units[unitID].tunnelerFinishedDigging = 1; diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index 4bb213948..b741c2c7b 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -50075,7 +50075,7 @@ SHC_3BB0A8C1_0x00531914 | 0.0% | Pending SHC_3BB0A8C1_0x00531915 | 0.0% | Pending -SHC_3BB0A8C1_0x00531920 | 25.6% | extra spills, frame size +SHC_3BB0A8C1_0x00531920 | 28.7% | extra spills, frame size SHC_3BB0A8C1_0x005323C0 | 0.0% | Pending From 6b4f5786ea92322cee1485839ec84c917b32bff7 Mon Sep 17 00:00:00 2001 From: Gynt Date: Mon, 28 Sep 2026 12:03:47 +0200 Subject: [PATCH 278/299] reimplement: SHC_3BB0A8C1_0x00537F60 64.89% LTCG edx across call --- .../UnitsState/getUnitStateTextParameterAndResourceType.cpp | 3 +-- status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/getUnitStateTextParameterAndResourceType.cpp b/src/OpenSHC/Map/Units/UnitsState/getUnitStateTextParameterAndResourceType.cpp index 1fb9dd000..1667cdf7f 100644 --- a/src/OpenSHC/Map/Units/UnitsState/getUnitStateTextParameterAndResourceType.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/getUnitStateTextParameterAndResourceType.cpp @@ -268,8 +268,7 @@ namespace Map { 115 or 112 */ - return (-(uint)(this->units[this->units[unitIndex].shootTargetedUnit].isStalked != 0) & 0xfffffffd) - + 0x73; + return this->units[this->units[unitIndex].shootTargetedUnit].isStalked != 0 ? 0x70 : 0x73; case 10: return (uint)(this->units[this->units[unitIndex].shootTargetedUnit].isStalked == 0) * 2 + 0x71; default: diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index b741c2c7b..f9cc07722 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -51263,7 +51263,7 @@ SHC_3BB0A8C1_0x00537E00 | 35.2% | orig has 2 separate loops SHC_3BB0A8C1_0x00537EE0 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x00537F60 | 62.5% | jump table order differs +SHC_3BB0A8C1_0x00537F60 | 64.9% | LTCG edx across call SHC_3BB0A8C1_0x005388DC | 0.0% | Pending From a942a9230ea39ec148c4a64b09068472847ab0c1 Mon Sep 17 00:00:00 2001 From: Gynt Date: Mon, 28 Sep 2026 12:03:47 +0200 Subject: [PATCH 279/299] reimplement: SHC_3BB0A8C1_0x00533D50 39.42% reg alloc --- .../UnitsState/updateUnitFadeAndVisibilityNearStructures.cpp | 2 +- status/addresses-SHC-3BB0A8C1.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/updateUnitFadeAndVisibilityNearStructures.cpp b/src/OpenSHC/Map/Units/UnitsState/updateUnitFadeAndVisibilityNearStructures.cpp index 578fa8990..cd21f5e89 100644 --- a/src/OpenSHC/Map/Units/UnitsState/updateUnitFadeAndVisibilityNearStructures.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/updateUnitFadeAndVisibilityNearStructures.cpp @@ -85,7 +85,7 @@ namespace Map { if (_isOnDefensiveStructure) { this->units[unitID].field171_0x308 = 1; } else if (_towerFadeType == 0) { - this->units[unitID].field171_0x308 = -(ushort)(_gateFadeType != 0) & 3; + this->units[unitID].field171_0x308 = _gateFadeType != 0 ? 3 : 0; } else { this->units[unitID].field171_0x308 = 2; } diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index f9cc07722..2ea113aed 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -50693,7 +50693,7 @@ SHC_3BB0A8C1_0x00533C70 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00533CA0 | 90.9% | loop exit shape differs -SHC_3BB0A8C1_0x00533D50 | 37.6% | branch shape differs +SHC_3BB0A8C1_0x00533D50 | 39.4% | reg alloc SHC_3BB0A8C1_0x00533F48 | 0.0% | Pending From 7aa128632d326e10c227428b32f1d3e8f908b187 Mon Sep 17 00:00:00 2001 From: Gynt Date: Mon, 28 Sep 2026 13:02:03 +0200 Subject: [PATCH 280/299] cleanup: calculateUnitMovementSpeed readability at equal match Numeric literals instead of char literals, drop the redundant (int)(uint) widening on the byte height, and reuse the already-loaded LogicLayer word instead of reloading it twice. The (char) casts stay: negativeHeight is a byte and the original compares it signed. Measured with try_styles.py: baseline, clean and logicflags all 26.40%. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01A4PvfebpUzaMXy93EutBjJ --- .../UnitsState/calculateUnitMovementSpeed.cpp | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/calculateUnitMovementSpeed.cpp b/src/OpenSHC/Map/Units/UnitsState/calculateUnitMovementSpeed.cpp index 1d0c46af4..2e9991a98 100644 --- a/src/OpenSHC/Map/Units/UnitsState/calculateUnitMovementSpeed.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/calculateUnitMovementSpeed.cpp @@ -43,13 +43,13 @@ namespace Map { if (_isInMoat != 0 && (DAT_TileMapState::instance.MacroLayer[_tile] & 0x3f) == 1) { _isInMoat = 0; } - if ((DAT_TileMapState::instance.LogicLayer[_tile] & 0x40000000U) != 0) { + if ((_logicFlags & 0x40000000) != 0) { _isInMoat = 1; } if ((_logicFlags & 0x800000) != 0) { this->units[unitID].calculatedMovementSpeed = this->units[unitID].movementSpeed; - } else if (this->units[unitID].terrainOrClimbHeight < (int)(uint)_tileHeight) { - int _heightDifference = (uint)_tileHeight - this->units[unitID].terrainOrClimbHeight; + } else if (this->units[unitID].terrainOrClimbHeight < _tileHeight) { + int _heightDifference = _tileHeight - this->units[unitID].terrainOrClimbHeight; /* the climb bands are split by halving, not as a flat ladder */ if (_heightDifference < 0x11) { if (_heightDifference < 0xc) { @@ -82,8 +82,8 @@ namespace Map { this->units[unitID].terrainOrClimbHeight = _tileHeight; this->units[unitID].calculatedMovementSpeed = this->units[unitID].movementSpeed; } - } else if ((int)(uint)_tileHeight < this->units[unitID].terrainOrClimbHeight) { - int _heightDifference = this->units[unitID].terrainOrClimbHeight - (uint)_tileHeight; + } else if (_tileHeight < this->units[unitID].terrainOrClimbHeight) { + int _heightDifference = this->units[unitID].terrainOrClimbHeight - _tileHeight; if (_heightDifference > 0x10) { this->units[unitID].terrainOrClimbHeight = _tileHeight; this->units[unitID].calculatedMovementSpeed = this->units[unitID].movementSpeed; @@ -120,31 +120,31 @@ namespace Map { } if (_isInMoat == 0) { if ((_logicFlags & 0x200000) != 0) { - if ((char)this->units[unitID].negativeHeight < '\x10') { + if ((char)this->units[unitID].negativeHeight < 0x10) { this->units[unitID].negativeHeight = this->units[unitID].negativeHeight + 4; } this->units[unitID].calculatedMovementSpeed = this->units[unitID].calculatedMovementSpeed + 2; } else if (this->units[unitID].negativeHeight != 0) { this->units[unitID].negativeHeight = this->units[unitID].negativeHeight - 8; - if ((char)this->units[unitID].negativeHeight < '\0') { + if ((char)this->units[unitID].negativeHeight < 0) { this->units[unitID].negativeHeight = 0; } this->units[unitID].calculatedMovementSpeed = this->units[unitID].calculatedMovementSpeed + 3; } } else { - if ((char)this->units[unitID].negativeHeight < '\x18') { + if ((char)this->units[unitID].negativeHeight < 0x18) { this->units[unitID].negativeHeight = this->units[unitID].negativeHeight + 4; } - if ((char)this->units[unitID].negativeHeight <= '\x04') { + if ((char)this->units[unitID].negativeHeight <= 4) { this->units[unitID].calculatedMovementSpeed = this->units[unitID].calculatedMovementSpeed + 3; - } else if ((char)this->units[unitID].negativeHeight < '\n') { + } else if ((char)this->units[unitID].negativeHeight < 10) { this->units[unitID].calculatedMovementSpeed = this->units[unitID].calculatedMovementSpeed + 4; } else { this->units[unitID].calculatedMovementSpeed = this->units[unitID].calculatedMovementSpeed + 6; } } this->units[unitID].field289_0x3ff = 0; - if ((DAT_TileMapState::instance.LogicLayer[_tile] & 8) != 0) { + if ((_logicFlags & 8) != 0) { MACRO_CALL_MEMBER(OpenSHC::Map::Units::TroopValueState_Func::registerSpottedEnemyTile, DAT_TroopValueState::ptr)(_tile); } From 5978fbcba5161f4cd3f9a0d7921f9582ca6e404c Mon Sep 17 00:00:00 2001 From: Gynt Date: Mon, 28 Sep 2026 13:04:11 +0200 Subject: [PATCH 281/299] reimplement: findNearestEnemyAndHeadTowardsIt 34.4% reg alloc Drop two Ghidra artifacts: the (_score + (_score >> 0x1f & 3)) >> 2 idiom is the compiler''s signed divide by 4, and the distance locals were typed dword while every use cast them back to int. Measured with try_styles.py: baseline 34.30%, div4 / signed_score / signed_all all 34.40%; kept signed_all as the one with no casts left. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01A4PvfebpUzaMXy93EutBjJ --- .../findNearestEnemyAndHeadTowardsIt.cpp | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/findNearestEnemyAndHeadTowardsIt.cpp b/src/OpenSHC/Map/Units/UnitsState/findNearestEnemyAndHeadTowardsIt.cpp index 4acd19010..62e8d576b 100644 --- a/src/OpenSHC/Map/Units/UnitsState/findNearestEnemyAndHeadTowardsIt.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/findNearestEnemyAndHeadTowardsIt.cpp @@ -30,8 +30,8 @@ namespace Map { int _playerID = this->units[unitID].owner; dword _area = (short)DAT_TileMapState::instance.PathConnectionLayer[this->units[unitID].tile]; this->unitDistanceComputationResultUnk = 100000; - dword _minDistance = 100000; - dword _chosenRawDistance = 0; + int _minDistance = 100000; + int _chosenRawDistance = 0; int _bestScore = 100000; int _foundEnemyID = 0; int _visionDivisor = 1; @@ -132,7 +132,7 @@ namespace Map { } else { _distanceY = this->units[_enemyUnitID].microYPosition - _microY; } - dword _approximateDistance; + int _approximateDistance; if (_distanceX < _distanceY) { /* pythagorean approximation */ _approximateDistance = (((_distanceX * 2) / 5) * _distanceX) / _distanceY + _distanceY; @@ -142,20 +142,20 @@ namespace Map { } else { _approximateDistance = (((_distanceY * 2) / 5) * _distanceY) / _distanceX + _distanceX; } - if ((int)_approximateDistance < (int)_minDistance) { + if (_approximateDistance < _minDistance) { _minDistance = _approximateDistance; } if (this->units[unitID].unitType == OpenSHC::Map::Units::UT_A_ASSASSIN && this->units[_enemyUnitID].isSelectable_OR_matchTime != 0 - && (int)_approximateDistance < (int)this->unitDistanceComputationResultUnk) { + && _approximateDistance < (int)this->unitDistanceComputationResultUnk) { this->unitDistanceComputationResultUnk = _approximateDistance; } if (_skipStanceSearch || _stanceBasedRange == 0 || this->units[unitID].lookForEnemy < 0) { continue; } - dword _score = _approximateDistance; + int _score = _approximateDistance; if (this->units[unitID]._someX_2 != 0 && _isRallying == 0 && _stanceBasedRange == 40) { - dword _savedDistanceX; + int _savedDistanceX; if (this->units[unitID]._someX_2 * 8 < this->units[_enemyUnitID].microXPosition) { _savedDistanceX = this->units[_enemyUnitID].microXPosition + this->units[unitID]._someX_2 * -8; } else { @@ -166,12 +166,12 @@ namespace Map { } else { _score = this->units[unitID]._someY_2 * 8 - this->units[_enemyUnitID].microYPosition; } - if ((int)_score <= (int)_savedDistanceX) { + if (_score <= _savedDistanceX) { _score = _savedDistanceX; } } - dword _rawDistance = _score; - if ((int)_score > _stanceBasedRange) { + int _rawDistance = _score; + if (_score > _stanceBasedRange) { continue; } if (this->units[_enemyUnitID].uid @@ -235,15 +235,15 @@ namespace Map { _score = _score + 0x19; break; case OpenSHC::Map::Units::UT_LORD: - _score = (_score + ((int)_score >> 0x1f & 3U)) >> 2; + _score = _score / 4; break; default: _score = _score * 4 + 200; } if (this->units[unitID].movementType_OR_targetUnitID == _enemyUnitID) { - _score = (int)_score / 2; + _score = _score / 2; } - if ((int)_score >= _bestScore) { + if (_score >= _bestScore) { continue; } int _enemyTotalHeight @@ -358,7 +358,7 @@ namespace Map { this->units[unitID]._someX_2 = 0; this->units[unitID].state.generic = OpenSHC::Map::Units::States::US_MOVE_TO_DESTINATION; } - if ((int)_minDistance > 32000) { + if (_minDistance > 32000) { _minDistance = 32000; } return _minDistance; From 4e058480d71eb611a71a0c25705c2ed55439cd05 Mon Sep 17 00:00:00 2001 From: Gynt Date: Mon, 28 Sep 2026 13:25:08 +0200 Subject: [PATCH 282/299] reimplement: restore signed power-of-two divisions in 8 functions The decompiler reports MSVC''s biased shift for a signed division by a power of two, "(x + (x >> 0x1f & 7U)) >> 3", literally. Rewriting the 22 sites in this namespace back to "x / 8" is what the original source said, and it matches considerably better: unitClimbing 32.5 -> 55.3 findEligibleUnitByTimeAndLocation 63.0 -> 77.8 ifOnADefensiveStructureSetDestination... 50.5 -> 64.9 checkTargetBuildingPossibilityOrState 26.5 -> 39.2 prepareProjectileTarget 42.5 -> 49.0 acquireShootTarget 39.3 -> 41.0 spawnUnit 46.8 -> 47.6 findNearestEnemyAndHeadTowardsIt 34.3 -> 34.4 Namespace average 74.32% -> 74.70%, no function regressed. The one site in processEntityDamageToUnit that measured 0.1% worse keeps the shift, with a remark saying why. Adds undiv.py (a balanced-paren rewriter; a regex cannot capture the dividend) and test_undiv.py covering the near-misses that must be left alone: a shift that disagrees with the mask, a mask that is not 2^k - 1, and a bias taken from another variable. Also fixes two ways the batch tools quietly report on the wrong thing: try_styles.py narrowed cmake/openshc-sources.txt.local to one function and never restored it, and reccmp_report.py read a stale diff.json without saying that it covered almost none of the build list. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01A4PvfebpUzaMXy93EutBjJ --- .../Units/UnitsState/acquireShootTarget.cpp | 18 ++++++------------ .../checkTargetBuildingPossibilityOrState.cpp | 4 +--- .../findEligibleUnitByTimeAndLocation.cpp | 3 +-- ...uctureSetDestinationInDirectionOfTarget.cpp | 8 ++------ .../UnitsState/prepareProjectileTarget.cpp | 9 ++++----- .../UnitsState/processEntityDamageToUnit.cpp | 1 + src/OpenSHC/Map/Units/UnitsState/spawnUnit.cpp | 8 ++------ .../Map/Units/UnitsState/unitClimbing.cpp | 8 ++------ 8 files changed, 19 insertions(+), 40 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/acquireShootTarget.cpp b/src/OpenSHC/Map/Units/UnitsState/acquireShootTarget.cpp index 3a5f09ff4..84f1cf319 100644 --- a/src/OpenSHC/Map/Units/UnitsState/acquireShootTarget.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/acquireShootTarget.cpp @@ -112,14 +112,10 @@ namespace Map { | OpenSHC::Map::Units::States::US_IDLEUnk) && DAT_GameState::instance.mapAndTime.playerTeams[this->units[_0x04_targetUnitID].owner] != DAT_GameState::instance.mapAndTime.playerTeams[_unitPlayerID]) { - int _0x04_yDifference = ((int)(_microYUnit + (_microYUnit >> 0x1f & 7U)) >> 3) - - ((int)((int)this->units[_0x04_targetUnitID].microYPosition - + ((int)this->units[_0x04_targetUnitID].microYPosition >> 0x1f & 7U)) - >> 3); - _xDifferenceToTarget = ((int)(_microXUnit + (_microXUnit >> 0x1f & 7U)) >> 3) - - ((int)((int)this->units[_0x04_targetUnitID].microXPosition - + ((int)this->units[_0x04_targetUnitID].microXPosition >> 0x1f & 7U)) - >> 3); + int _0x04_yDifference + = ((int)_microYUnit / 8) - ((int)this->units[_0x04_targetUnitID].microYPosition / 8); + _xDifferenceToTarget + = ((int)_microXUnit / 8) - ((int)this->units[_0x04_targetUnitID].microXPosition / 8); if (_xDifferenceToTarget * _xDifferenceToTarget + _0x04_yDifference * _0x04_yDifference <= _rangeSquared) { int _shootDistanceScore @@ -290,10 +286,8 @@ namespace Map { } _xDifferenceToTarget = (int)this->units[_enemy].microYPosition; int iVar7 = (int)this->units[_enemy].microXPosition; - int _yDifferenceToTarget = ((int)(_microYUnit + (_microYUnit >> 0x1f & 7U)) >> 3) - - ((int)(_xDifferenceToTarget + (_xDifferenceToTarget >> 0x1f & 7U)) >> 3); - _xDifferenceToTarget = ((int)(_microXUnit + (_microXUnit >> 0x1f & 7U)) >> 3) - - ((int)(iVar7 + (iVar7 >> 0x1f & 7U)) >> 3); + int _yDifferenceToTarget = ((int)_microYUnit / 8) - ((int)_xDifferenceToTarget / 8); + _xDifferenceToTarget = ((int)_microXUnit / 8) - ((int)iVar7 / 8); if (_rangeSquared < _xDifferenceToTarget * _xDifferenceToTarget + _yDifferenceToTarget * _yDifferenceToTarget) continue; diff --git a/src/OpenSHC/Map/Units/UnitsState/checkTargetBuildingPossibilityOrState.cpp b/src/OpenSHC/Map/Units/UnitsState/checkTargetBuildingPossibilityOrState.cpp index eec44b3c8..55ccc8d02 100644 --- a/src/OpenSHC/Map/Units/UnitsState/checkTargetBuildingPossibilityOrState.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/checkTargetBuildingPossibilityOrState.cpp @@ -33,9 +33,7 @@ namespace Map { int _shootTargetMicroY = this->units[unitID].shootTargetMicroY; return (BOOLEnum)(MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func:: checkEnemyBuildingOrDefensiveStructureWithin12Tiles, - DAT_PathFindingState::ptr)(_playerID, - (_shootTargetMicroX + (_shootTargetMicroX >> 0x1f & 7U)) >> 3, - (_shootTargetMicroY + (_shootTargetMicroY >> 0x1f & 7U)) >> 3) + DAT_PathFindingState::ptr)(_playerID, _shootTargetMicroX / 8, _shootTargetMicroY / 8) != FALSE); } diff --git a/src/OpenSHC/Map/Units/UnitsState/findEligibleUnitByTimeAndLocation.cpp b/src/OpenSHC/Map/Units/UnitsState/findEligibleUnitByTimeAndLocation.cpp index 2e83a0da5..c10abc7ca 100644 --- a/src/OpenSHC/Map/Units/UnitsState/findEligibleUnitByTimeAndLocation.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/findEligibleUnitByTimeAndLocation.cpp @@ -49,8 +49,7 @@ namespace Map { OpenSHC::Map::Navigation::DirectionAlgorithmState_Func::setAxisBasedDistanceResult, DAT_DirectionAlgorithmState::ptr)( unitXPosition, unitYPosition, this->units[_candidateUnitID].x, this->units[_candidateUnitID].y); - /* this formula means divide by 4 and round it up. */ - _score = _score - ((_distance + (_distance >> 0x1f & 3U)) >> 2); + _score = _score - (_distance / 4); } if (_bestScore < _score) { _bestScore = _score; diff --git a/src/OpenSHC/Map/Units/UnitsState/ifOnADefensiveStructureSetDestinationInDirectionOfTarget.cpp b/src/OpenSHC/Map/Units/UnitsState/ifOnADefensiveStructureSetDestinationInDirectionOfTarget.cpp index ef7ec8560..6bfea2724 100644 --- a/src/OpenSHC/Map/Units/UnitsState/ifOnADefensiveStructureSetDestinationInDirectionOfTarget.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/ifOnADefensiveStructureSetDestinationInDirectionOfTarget.cpp @@ -53,12 +53,8 @@ namespace Map { = (short)DAT_BuildingsState::instance.buildings[this->units[unitID].targetID_OR_targetBuildingID].y; } else if (this->units[unitID].targetingType == OpenSHC::Map::Units::UIT_ATTACK_LAND || this->units[unitID].shootTargetedUnit == -2) { - _targetX - = (this->units[unitID].shootTargetMicroX + (this->units[unitID].shootTargetMicroX >> 0x1f & 7U)) - >> 3; - _targetY - = (this->units[unitID].shootTargetMicroY + (this->units[unitID].shootTargetMicroY >> 0x1f & 7U)) - >> 3; + _targetX = this->units[unitID].shootTargetMicroX / 8; + _targetY = this->units[unitID].shootTargetMicroY / 8; } else { _targetX = this->units[this->units[unitID].shootTargetedUnit].x; _targetY = this->units[this->units[unitID].shootTargetedUnit].y; diff --git a/src/OpenSHC/Map/Units/UnitsState/prepareProjectileTarget.cpp b/src/OpenSHC/Map/Units/UnitsState/prepareProjectileTarget.cpp index 3878c4953..dc06e3025 100644 --- a/src/OpenSHC/Map/Units/UnitsState/prepareProjectileTarget.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/prepareProjectileTarget.cpp @@ -28,12 +28,12 @@ namespace Map { targetID has negative height (walking in pitch or moat) */ if (this->units[targetID].stateBasedSpeed == 0) { if (this->units[targetID].calculatedMovementSpeed < 2) { - _adjustment = (short)((_lead + (_lead >> 0x1f & 0xfU)) >> 4); + _adjustment = (short)(_lead / 16); } else { _adjustment = (short)(_lead / (this->units[targetID].calculatedMovementSpeed << 4)); } } else { - _adjustment = (short)((_lead + (_lead >> 0x1f & 7U)) >> 3); + _adjustment = (short)(_lead / 8); } short _targetFacing = this->units[targetID].facingDirection; if (_targetFacing == 0) { @@ -127,12 +127,11 @@ namespace Map { return _unhandledTypeResult; } if ((_rng & 7) < 2) { - _scatter = (_scatter + (_scatter >> 0x1f & 3U)) >> 2; + _scatter = _scatter / 4; if (_scatter == 0) { _scatter = 1; } - int _horizontalRng - = ((int)(_rng + ((int)_rng >> 0x1f & 0x1ffU)) >> 9) + this->units[shooterID].fixedRng; + int _horizontalRng = ((int)_rng / 512) + this->units[shooterID].fixedRng; if (_horizontalRng < 0) { _horizontalRng = -_horizontalRng; } diff --git a/src/OpenSHC/Map/Units/UnitsState/processEntityDamageToUnit.cpp b/src/OpenSHC/Map/Units/UnitsState/processEntityDamageToUnit.cpp index 257fd05e5..bdd4062bf 100644 --- a/src/OpenSHC/Map/Units/UnitsState/processEntityDamageToUnit.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/processEntityDamageToUnit.cpp @@ -313,6 +313,7 @@ namespace Map { _damage = DAT_UnitPropertiesDefinedData::instance.ARROW_DAMAGE[(short)_entityType_2]; if (_entityType_2 == OpenSHC::Map::Units::UT_E_LADDER && this->units[unitID].state.generic == (UnitState)3) { + /* the compiler's biased shift matches here where a plain /4 does not */ _damage = (int)(_damage + (_damage >> 0x1f & 3U)) >> 2; } } else if (_entityType == OpenSHC::Map::Entities::ET_SLINGER) { diff --git a/src/OpenSHC/Map/Units/UnitsState/spawnUnit.cpp b/src/OpenSHC/Map/Units/UnitsState/spawnUnit.cpp index cc57c350d..663fabce7 100644 --- a/src/OpenSHC/Map/Units/UnitsState/spawnUnit.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/spawnUnit.cpp @@ -57,15 +57,11 @@ namespace Map { } else if (unitType == OpenSHC::Map::Units::UT_CAGEDOG) { this->units[_unitID].calculatedOwnerPlayerIndex = 0; } - short _y - = (short)((this->units[_unitID].microYPosition + (this->units[_unitID].microYPosition >> 0x1f & 7U)) - >> 3); + short _y = (short)(this->units[_unitID].microYPosition / 8); this->units[_unitID].mimicCurrentYPosition = _y; this->units[_unitID].y = _y; this->units[_unitID].destinationY_2Unk = _y; - short _x - = (short)((this->units[_unitID].microXPosition + (this->units[_unitID].microXPosition >> 0x1f & 7U)) - >> 3); + short _x = (short)(this->units[_unitID].microXPosition / 8); this->units[_unitID].mimicCurrentXPosition = _x; this->units[_unitID].x = _x; this->units[_unitID].destinationX_2Unk = _x; diff --git a/src/OpenSHC/Map/Units/UnitsState/unitClimbing.cpp b/src/OpenSHC/Map/Units/UnitsState/unitClimbing.cpp index 5dbe7852f..56db511b0 100644 --- a/src/OpenSHC/Map/Units/UnitsState/unitClimbing.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/unitClimbing.cpp @@ -111,16 +111,12 @@ namespace Map { /* Climbing up */ this->units[unitID].animationFrame = (char)DAT_UnitPropertiesDefinedData::instance.Frames_Shared_UnitClimbingUp - .ANIM_Frames_Shared_UnitClimbingUp[(this->units[unitID].field203_0x35c - + (this->units[unitID].field203_0x35c >> 0x1f & 7U)) - >> 3]; + .ANIM_Frames_Shared_UnitClimbingUp[this->units[unitID].field203_0x35c / 8]; } else { /* Climbing down */ this->units[unitID].animationFrame = (char)DAT_UnitPropertiesDefinedData::instance - .Frames_Shared_UnitClimbingDown[(this->units[unitID].field203_0x35c - + (this->units[unitID].field203_0x35c >> 0x1f & 7U)) - >> 3]; + .Frames_Shared_UnitClimbingDown[this->units[unitID].field203_0x35c / 8]; } this->units[unitID].gfxNumber = this->units[unitID].animationSheetFrameOffset + this->units[unitID].animationFrame * 8 + -8 From 78e3e2ba2d39f1e61dd248b6bdef11e7d46b1a7a Mon Sep 17 00:00:00 2001 From: Gynt Date: Mon, 28 Sep 2026 13:37:27 +0200 Subject: [PATCH 283/299] reimplement: restore signed power-of-two remainders in updateUnits The compiler cannot mask to take "x % 16" of a signed int, because the result keeps x''s sign, so it masks the low bits together with the sign bit and repairs the negative case afterwards. The decompiler reports both halves: v = x & 0x8000000f; if ((int)v < 0) { v = (v - 1 | 0xfffffff0) + 1; } That is "v = x % 16". Five sites, four of them in updateUnits: updateUnits 35.1 -> 37.8 getUnitStateTextParameterAndResourceType 64.8 -> 64.9 The repair exists only because the operand is signed -- an unsigned remainder is a bare "and" -- so the dividend has to stay signed in our source as well. fixedRng and the unit slot ID are uint fields and the decompiler''s "+ 4U" makes its sum unsigned too, so unmod.py drops the U suffixes and casts to int; without that the match would drop rather than rise. Namespace average 74.70% -> 74.72%, nothing regressed. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01A4PvfebpUzaMXy93EutBjJ --- ...tUnitStateTextParameterAndResourceType.cpp | 5 +-- .../Map/Units/UnitsState/updateUnits.cpp | 32 ++++++------------- 2 files changed, 11 insertions(+), 26 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/getUnitStateTextParameterAndResourceType.cpp b/src/OpenSHC/Map/Units/UnitsState/getUnitStateTextParameterAndResourceType.cpp index 1667cdf7f..9d2d2554d 100644 --- a/src/OpenSHC/Map/Units/UnitsState/getUnitStateTextParameterAndResourceType.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/getUnitStateTextParameterAndResourceType.cpp @@ -34,10 +34,7 @@ namespace Map { This is an optimized % 4, producing -3 to 3 */ - uint _rng_0x79 = this->units[unitIndex].fixedRng & 0x80000003; - if ((int)_rng_0x79 < 0) { - _rng_0x79 = (_rng_0x79 - 1 | 0xfffffffc) + 1; - } + uint _rng_0x79 = (int)this->units[unitIndex].fixedRng % 4; /* "Wandering around Eating fire diff --git a/src/OpenSHC/Map/Units/UnitsState/updateUnits.cpp b/src/OpenSHC/Map/Units/UnitsState/updateUnits.cpp index 39acfbdc6..12488ba8e 100644 --- a/src/OpenSHC/Map/Units/UnitsState/updateUnits.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/updateUnits.cpp @@ -63,10 +63,7 @@ namespace Map { short _buildingID; BuildingTypeShort _buildingType; - _rngNumber8 = (int)SEC_RNG::instance.currentNumber2 & 0x8000000f; - if ((int)_rngNumber8 < 0) { - _rngNumber8 = (_rngNumber8 - 1 | 0xfffffff0) + 1; - } + _rngNumber8 = (int)SEC_RNG::instance.currentNumber2 % 16; MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( 80400, '\0', (void*)((int)(DAT_TileMapState::instance.OccupancyLayer))); DAT_GameState::instance.playerDataArray[0].healerCount = 0; @@ -129,10 +126,7 @@ namespace Map { = DAT_GameState::instance.playerDataArray[_buildingID].unblessedPeopleCountUnk + 1; } _currentUnitID = DAT_CurrentUnitSlotID::instance; - _unitIDBased8value = _currentUnitID & 0x8000000f; - if ((int)_unitIDBased8value < 0) { - _unitIDBased8value = (_unitIDBased8value - 1 | 0xfffffff0) + 1; - } + _unitIDBased8value = (int)_currentUnitID % 16; if (_unitIDBased8value == _rngNumber8) { int _unitTile = this->units[_currentUnitID].tile; if (DAT_TileMapState::instance.PathConnectionLayer[_unitTile] == 0 @@ -854,24 +848,18 @@ namespace Map { *piVar1 = *piVar1 + this->units[DAT_CurrentUnitSlotID::instance].field218_0x37e * 8; break; case 0x16: - uVar9 = (int)this->units[DAT_CurrentUnitSlotID::instance] - .facingDirectionMapOrientationCorrected - + 4U - & 0x80000007; - if ((int)uVar9 < 0) { - uVar9 = (uVar9 - 1 | 0xfffffff8) + 1; - } + uVar9 = ((int)this->units[DAT_CurrentUnitSlotID::instance] + .facingDirectionMapOrientationCorrected + + 4) + % 8; this->units[DAT_CurrentUnitSlotID::instance].gfxNumber = uVar9 + 0x151; piVar1 = &this->units[DAT_CurrentUnitSlotID::instance].gfxNumber; *piVar1 = *piVar1 + ((byte)this->units[DAT_CurrentUnitSlotID::instance].field218_0x37e & 3) * 8; - uVar9 = (int)this->units[DAT_CurrentUnitSlotID::instance] - .facingDirectionMapOrientationCorrected - + 4U - & 0x80000007; - if ((int)uVar9 < 0) { - uVar9 = (uVar9 - 1 | 0xfffffff8) + 1; - } + uVar9 = ((int)this->units[DAT_CurrentUnitSlotID::instance] + .facingDirectionMapOrientationCorrected + + 4) + % 8; _troopValue = uVar9 + 0x1d1; this->units[DAT_CurrentUnitSlotID::instance].imageIDUnk = _troopValue; piVar1 = &this->units[DAT_CurrentUnitSlotID::instance].imageIDUnk; From aed965c92eebbea7bc808280b0780610a640f1d4 Mon Sep 17 00:00:00 2001 From: Gynt Date: Mon, 28 Sep 2026 13:39:14 +0200 Subject: [PATCH 284/299] reimplement: processEntityDamageToUnit 31.4% reg alloc The health bar was carrying the decompiler''s mangled magic-multiply for a division by 10: (x / 10 + (x >> 0xf)) - (short)((longlong)(int)x * 0x66666667 >> 0x3f) Both correction terms are "-1 when x is negative, 0 otherwise", so they cancel exactly and the whole expression is x / 10 -- a health percentage scaled to a ten-segment bar, which is what the field is called. The decompiler had also reused _entityShootingUnitID to hold that percentage; the value now goes straight into the field it belongs to. 28.7% -> 31.4%. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01A4PvfebpUzaMXy93EutBjJ --- .../Map/Units/UnitsState/processEntityDamageToUnit.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/processEntityDamageToUnit.cpp b/src/OpenSHC/Map/Units/UnitsState/processEntityDamageToUnit.cpp index bdd4062bf..4ab2d0675 100644 --- a/src/OpenSHC/Map/Units/UnitsState/processEntityDamageToUnit.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/processEntityDamageToUnit.cpp @@ -368,10 +368,8 @@ namespace Map { int _healthPercentage_2 = MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::DirectionAlgorithmState_Func::computeHealthPercentage, DAT_DirectionAlgorithmState::ptr)(_unitHealth, this->units[unitID].maxHealth); - _entityShootingUnitID = (short)_healthPercentage_2; - this->units[unitID].healthPercentage = _entityShootingUnitID; - this->units[unitID].healthbar = (_entityShootingUnitID / 10 + (_entityShootingUnitID >> 0xf)) - - (short)((longlong)(int)_entityShootingUnitID * 0x66666667 >> 0x3f); + this->units[unitID].healthPercentage = (short)_healthPercentage_2; + this->units[unitID].healthbar = this->units[unitID].healthPercentage / 10; if (_unitType == OpenSHC::Map::Units::UT_BREWER || _unitType == OpenSHC::Map::Units::UT_TANNER || _unitType == OpenSHC::Map::Units::UT_LADY || _unitType == OpenSHC::Map::Units::UT_MOTHER || (_unitType == OpenSHC::Map::Units::UT_CHILD && (this->units[unitID].spriteID == 0x81))) { From df3af4c609ea505a077195828de6bdf021564125 Mon Sep 17 00:00:00 2001 From: Gynt Date: Mon, 28 Sep 2026 13:46:38 +0200 Subject: [PATCH 285/299] fix: three lost shared blocks in processEntityDamageToUnit; 28.7% -> 36.4% All three are the same mistake: the decompiler''s gotos jumped into blocks with several predecessors, and removing the gotos dropped the block instead of duplicating it. 1. Flying cow damage. The original falls through to a block it shares with the other siege projectiles: uVar5 = -(uint)(_entityType_2 != UT_S_SHIELD) & 0x1c2; LAB_00531f5d: _damage = uVar5 + 0x32; We kept the first line and lost the second, so a cow assigned a local nothing read and left _damage holding the entity height from the altitude check above. It is now 50 against a shield and 500 against anything else. 2. Hit sounds 2 to 7 were unreachable. The break sat outside its if: if (_hitSoundVariant == 1) sfxOffsetInArray = FX_BODY_HIT2; break; // always taken if (_hitSoundVariant == 2) { ... } // dead so every non-siege unit played the same hit sound. 3. The UT_S_SHIELD case set no sound at all and fell out of the switch, leaving sfxOffsetInArray uninitialised on that path. In the original that case shares LAB_0053231d with hit sound 1, which sets FX_BODY_HIT2. Also clears the 25 decompiler-generated names here: bVar4 is the flag that picks FX_GIRL_DIE, so it is _usesFemaleDeathScream; uVar5 was serving three unrelated purposes and is split; sVar3 and the psVar1 field pointer are gone in favour of the fields themselves. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01A4PvfebpUzaMXy93EutBjJ --- .../UnitsState/processEntityDamageToUnit.cpp | 57 ++++++++++--------- 1 file changed, 30 insertions(+), 27 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/processEntityDamageToUnit.cpp b/src/OpenSHC/Map/Units/UnitsState/processEntityDamageToUnit.cpp index 4ab2d0675..df814394a 100644 --- a/src/OpenSHC/Map/Units/UnitsState/processEntityDamageToUnit.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/processEntityDamageToUnit.cpp @@ -38,7 +38,6 @@ namespace Map { { int _cowDiseaseDamage; - uint uVar5; int _unitHeight; eSFX sfxOffsetInArray; UnitTypeShort _entityType_2; @@ -51,7 +50,7 @@ namespace Map { int _unknown = (int)this->units[unitID].tribeID; int _unitIsSiegeEngine = 0; int _siegeProjectile = 0; - int bVar4 = 0; + int _usesFemaleDeathScream = 0; UnitTypeShort _unitType = this->units[unitID].unitType; short _entityShootingUnitID = DAT_EntityState::instance.entityArray[entityID].unitID_OR_seaGullID; int _entityShootingUnitID_2 = (int)_entityShootingUnitID; @@ -223,7 +222,8 @@ namespace Map { if (_entityType_2 == OpenSHC::Map::Units::UT_LORD) { _damage = 0x32; } else { - uVar5 = _entityType_2 == OpenSHC::Map::Units::UT_S_SHIELD ? 0 : 0x1c2; + /* flying cow: 50 against a shield, 500 against anything else */ + _damage = _entityType_2 == OpenSHC::Map::Units::UT_S_SHIELD ? 0x32 : 0x1f4; } } else if (_entityType == OpenSHC::Map::Entities::ET_MANGONEL) { /* @@ -252,8 +252,8 @@ namespace Map { } } else { if (_entityType != OpenSHC::Map::Entities::ET_BALLISTA) { - uVar5 = this->units[unitID].unitType == OpenSHC::Map::Units::UT_LORD ? 0 : 0x74fe; - _damage = uVar5 + 0x32; + /* every other siege projectile: 50 against the lord, 30000 otherwise */ + _damage = this->units[unitID].unitType == OpenSHC::Map::Units::UT_LORD ? 0x32 : 0x7530; } /* tower ballista and fire ballista damage @@ -346,15 +346,13 @@ namespace Map { this->units[unitID].health = 0; } if (_entityShootingUnitID_2 != 0) { - short sVar3 = this->units[unitID].field97_0xd0; - if (sVar3 < 1000) { - this->units[unitID].field97_0xd0 = sVar3 + 200; + if (this->units[unitID].field97_0xd0 < 1000) { + this->units[unitID].field97_0xd0 = this->units[unitID].field97_0xd0 + 200; } - short* psVar1 = &DAT_TribesState::instance.tribes[_unknown].someUnitArrayIndex; - *psVar1 = *psVar1 + 1; - sVar3 = DAT_TribesState::instance.tribes[_unknown].someUnitArrayIndex; + DAT_TribesState::instance.tribes[_unknown].someUnitArrayIndex + = DAT_TribesState::instance.tribes[_unknown].someUnitArrayIndex + 1; DAT_TribesState::instance.tribes[_unknown].countdown = 100; - if (9 < sVar3) { + if (9 < DAT_TribesState::instance.tribes[_unknown].someUnitArrayIndex) { DAT_TribesState::instance.tribes[_unknown].someUnitArrayIndex = 0; } DAT_TribesState::instance.tribes[_unknown] @@ -373,7 +371,7 @@ namespace Map { if (_unitType == OpenSHC::Map::Units::UT_BREWER || _unitType == OpenSHC::Map::Units::UT_TANNER || _unitType == OpenSHC::Map::Units::UT_LADY || _unitType == OpenSHC::Map::Units::UT_MOTHER || (_unitType == OpenSHC::Map::Units::UT_CHILD && (this->units[unitID].spriteID == 0x81))) { - bVar4 = 1; + _usesFemaleDeathScream = 1; } bool _shootingUnitID = this->units[_entityShootingUnitID_2].unitType == OpenSHC::Map::Units::UT_A_SLINGER; if ((_unitHealth < 1) && (this->units[unitID].dying == 0)) { @@ -390,9 +388,10 @@ namespace Map { ? OpenSHC::Map::Units::States::US_STONE_DEATH_01 : (UnitState)(OpenSHC::Map::Units::States::US_STONE_DEATH_01 - 3); } - byte bVar2 = this->units[unitID].isStalked; + /* read before the write below, which the original also ordered this way */ + byte _wasStalked = this->units[unitID].isStalked; this->units[unitID].tunnelerFinishedDigging = 1; - if (bVar2 == 0) { + if (_wasStalked == 0) { switch (this->units[unitID].unitType) { case OpenSHC::Map::Units::UT_S_CATAPULT: case OpenSHC::Map::Units::UT_S_MANGONEL: @@ -416,7 +415,7 @@ namespace Map { sfxOffsetInArray = OpenSHC::DE::SHCDE::FX_SIEGE_DIE; break; } - if (bVar4) { + if (_usesFemaleDeathScream) { MACRO_CALL_MEMBER(OpenSHC::Audio::SFX::SFXState_Func::playSFXAtLocation, DAT_SFXState::ptr)( this->units[unitID].x, this->units[unitID].y, OpenSHC::DE::SHCDE::FX_GIRL_DIE); if (_shootingUnitID) { @@ -452,32 +451,33 @@ namespace Map { case OpenSHC::Map::Units::UT_S_FBALLISTA: sfxOffsetInArray = OpenSHC::DE::SHCDE::FX_WOOD_HIT; break; - default: - uVar5 = this->units[unitID].fixedRng & 7; - if (uVar5 != 0) { - if (uVar5 == 1) + default: { + uint _hitSoundVariant = this->units[unitID].fixedRng & 7; + if (_hitSoundVariant != 0) { + if (_hitSoundVariant == 1) { sfxOffsetInArray = OpenSHC::DE::SHCDE::FX_BODY_HIT2; - break; - if (uVar5 == 2) { + break; + } + if (_hitSoundVariant == 2) { sfxOffsetInArray = OpenSHC::DE::SHCDE::FX_BODY_HIT3; break; } - if (uVar5 == 3) { + if (_hitSoundVariant == 3) { sfxOffsetInArray = OpenSHC::DE::SHCDE::FX_BODY_HIT4; break; } - if (uVar5 == 4) { + if (_hitSoundVariant == 4) { sfxOffsetInArray = OpenSHC::DE::SHCDE::FX_BODY_HIT5; } else { - if (uVar5 == 5) { + if (_hitSoundVariant == 5) { sfxOffsetInArray = OpenSHC::DE::SHCDE::FX_BODY_HIT6; break; } - if (uVar5 == 6) { + if (_hitSoundVariant == 6) { sfxOffsetInArray = OpenSHC::DE::SHCDE::FX_BODY_HIT7; break; } - if (uVar5 != 7) { + if (_hitSoundVariant != 7) { return TRUE; } sfxOffsetInArray = OpenSHC::DE::SHCDE::FX_BODY_HIT8; @@ -486,6 +486,7 @@ namespace Map { } sfxOffsetInArray = OpenSHC::DE::SHCDE::FX_BODY_HIT; break; + } case OpenSHC::Map::Units::UT_LORD: return TRUE; case OpenSHC::Map::Units::UT_S_SHIELD: @@ -493,6 +494,8 @@ namespace Map { < 1) { return TRUE; } + sfxOffsetInArray = OpenSHC::DE::SHCDE::FX_BODY_HIT2; + break; } } } From cad945385255a58033a47b27c450d36d8cd24f12 Mon Sep 17 00:00:00 2001 From: Gynt Date: Mon, 28 Sep 2026 14:34:16 +0200 Subject: [PATCH 286/299] cleanup: name acquireShootTarget locals at equal match All 62 decompiler-generated names are gone. sVar9 was one register the decompiler had merged across seven unrelated values -- a manned engine target, a saved destination x, a pitch ditch index, a building index through the same field, an enemy tribe id, the chosen target and an attack tile y -- so it is split rather than renamed. Three sites share the identical line "shootTargetedUnit = sVar9;", so this was done by attributing each read to the assignment that most recently preceded it, not by matching text. iVar7 was merged across three values, one of which hid a trap: the old value is still an argument to the call that overwrites it. && (iVar7 = arrowShootingRelated(..., iVar7, ...), 0 < iVar7) The call is now lifted out of the condition, so the enemy y it reads and the flight distance it returns are separate variables. Measured with try_styles.py: baseline and named both 41.00%. Adds unptr.py and test_unptr.py for the field-walking pointers, and closes two ways the batch tools reported on a stale build: build_quiet.py now exits non-zero on BUILD_FAIL so "build && report" stops, and load_diff() warns when a source file is newer than diff.json. build.bat exits 0 even when compilation fails, so without these reccmp silently reports the previous DLL''s numbers -- which it did here, and the unchanged figure was mistaken for a neutral change. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01A4PvfebpUzaMXy93EutBjJ --- .../Units/UnitsState/acquireShootTarget.cpp | 162 +++++++++--------- 1 file changed, 82 insertions(+), 80 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/acquireShootTarget.cpp b/src/OpenSHC/Map/Units/UnitsState/acquireShootTarget.cpp index 84f1cf319..71d019443 100644 --- a/src/OpenSHC/Map/Units/UnitsState/acquireShootTarget.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/acquireShootTarget.cpp @@ -30,9 +30,6 @@ namespace Map { BOOLEnum UnitsState::acquireShootTarget(int unitID) { - UnitTypeShort UVar4; - BOOLEnum BVar6; - short sVar9; int _xDifferenceToTarget; int _entityType; int _unitPlayerID = (int)this->units[unitID].owner; @@ -41,11 +38,11 @@ namespace Map { int _unitTotalHeight = (int)this->units[unitID].buildingHeight + (int)this->units[unitID].terrainOrClimbHeight; int _validTargetID = 0; - int local_30 = 100000; - int local_8 = 0; - int local_2c = 100000; - int local_10 = 0; - int local_c = 0; + int _bestScore = 100000; + int _shotDistance = 0; + int _bestUntargetedScore = 100000; + int _untargetedTargetID = 0; + int _untargetedShotDistance = 0; switch (this->units[unitID].unitType) { case OpenSHC::Map::Units::UT_E_XBOW: _entityType = 7; @@ -96,17 +93,17 @@ namespace Map { fetch the targetedUnitID */ - sVar9 = this->units[unitID].targetedUnitID__OR__engineerMannedSiegeEngineRef; - int _0x04_targetUnitID = (int)sVar9; + short _mannedEngineTargetID = this->units[unitID].targetedUnitID__OR__engineerMannedSiegeEngineRef; + int _0x04_targetUnitID = (int)_mannedEngineTargetID; if (this->units[_0x04_targetUnitID].uid == this->units[unitID] .targetedUnitUIDUnk_OR_someAppearTileUnk_OR_buildingUID_OR_pitchDitchUID_OR_entityUID && this->units[_0x04_targetUnitID].dying == 0 && this->units[_0x04_targetUnitID].logicalState == OpenSHC::Map::Units::ULS_NORMAL) { - BVar6 + BOOLEnum _targetIsAliveCitizen = MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::checkIfCitizenUnitIsAliveBasedOnState, this)(_0x04_targetUnitID); - if (BVar6 == FALSE + if (_targetIsAliveCitizen == FALSE && this->units[_0x04_targetUnitID].state.generic != (OpenSHC::Map::Units::States::US_STONE_DEATH_03 | OpenSHC::Map::Units::States::US_IDLEUnk) @@ -126,8 +123,8 @@ namespace Map { (int)(this->units[_0x04_targetUnitID].buildingHeight + 0x1a + this->units[_0x04_targetUnitID].terrainOrClimbHeight)); if (_shootDistanceScore <= 0 - || (UVar4 = this->units[unitID].unitType, UVar4 == OpenSHC::Map::Units::UT_S_MANGONEL) - || UVar4 == OpenSHC::Map::Units::UT_S_BALLISTA) { + || this->units[unitID].unitType == OpenSHC::Map::Units::UT_S_MANGONEL + || this->units[unitID].unitType == OpenSHC::Map::Units::UT_S_BALLISTA) { if (this->units[unitID].unitType == OpenSHC::Map::Units::UT_HUNTER) { return FALSE; } @@ -137,7 +134,7 @@ namespace Map { this->units[unitID].shootTargetZ = this->units[_0x04_targetUnitID].terrainOrClimbHeight; return TRUE; } - this->units[unitID].shootTargetedUnit = sVar9; + this->units[unitID].shootTargetedUnit = _mannedEngineTargetID; this->units[unitID].targetUID = this->units[_0x04_targetUnitID].uid; this->units[unitID].distanceToEnemyUnitLadders = (short)_shootDistanceScore; this->units[unitID].shootTargetMicroX = this->units[_0x04_targetUnitID].microXPosition; @@ -167,13 +164,13 @@ namespace Map { } } } - sVar9 = this->units[unitID]._someX_2; + short _savedDestinationX = this->units[unitID]._someX_2; this->units[unitID].targetedUnitID__OR__engineerMannedSiegeEngineRef = 0; this->units[unitID].shootTargetedUnit = 0; this->units[unitID].targetingType = OpenSHC::Map::Units::UIT_NO_INSTRUCTION_OR_MOVEUnk; - if (sVar9 != 0) { + if (_savedDestinationX != 0) { MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::setDestinationForUnit, this)( - unitID, (uint)(sVar9), (uint)((int)this->units[unitID]._someY_2), 0); + unitID, (uint)(_savedDestinationX), (uint)((int)this->units[unitID]._someY_2), 0); this->units[unitID]._someX_2 = 0; this->units[unitID]._someY_2 = 0; this->units[unitID].moveDelay = 0; @@ -187,9 +184,9 @@ namespace Map { get the workplace building id */ - sVar9 = this->units[unitID].targetID_OR_targetBuildingID; + short _ditchID = this->units[unitID].targetID_OR_targetBuildingID; int _brazierEntityID; - if (DAT_TileMapState::instance.pitchDitches[sVar9].uid + if (DAT_TileMapState::instance.pitchDitches[_ditchID].uid == this->units[unitID] .targetedUnitUIDUnk_OR_someAppearTileUnk_OR_buildingUID_OR_pitchDitchUID_OR_entityUID && (_brazierEntityID = MACRO_CALL_MEMBER(OpenSHC::Map::Entities::EntityState_Func::isBrazierNearby, @@ -197,24 +194,25 @@ namespace Map { (int)(( int)(this->units[unitID].buildingHeight + this->units[unitID].terrainOrClimbHeight))), _brazierEntityID != 0)) { - this->units[unitID].shootTargetMicroX = DAT_TileMapState::instance.pitchDitches[sVar9].x * 8 + 4; - this->units[unitID].shootTargetMicroY = DAT_TileMapState::instance.pitchDitches[sVar9].y * 8 + 4; + this->units[unitID].shootTargetMicroX = DAT_TileMapState::instance.pitchDitches[_ditchID].x * 8 + 4; + this->units[unitID].shootTargetMicroY = DAT_TileMapState::instance.pitchDitches[_ditchID].y * 8 + 4; this->units[unitID].shootTargetZ = (ushort)DAT_TileMapState::instance - .HeightLayer[DAT_TileMapState::instance.pitchDitches[sVar9].tile]; + .HeightLayer[DAT_TileMapState::instance.pitchDitches[_ditchID].tile]; this->units[unitID].shootTargetedUnit = -1; return TRUE; } } else if (this->units[unitID].targetingType == OpenSHC::Map::Units::UIT_ATTACK_BUILDING) { - sVar9 = this->units[unitID].targetID_OR_targetBuildingID; - if (DAT_BuildingsState::instance.buildings[sVar9].uid + short _buildingID = this->units[unitID].targetID_OR_targetBuildingID; + if (DAT_BuildingsState::instance.buildings[_buildingID].uid == this->units[unitID] .targetedUnitUIDUnk_OR_someAppearTileUnk_OR_buildingUID_OR_pitchDitchUID_OR_entityUID) { - this->units[unitID].shootTargetMicroX = DAT_BuildingsState::instance.buildings[sVar9].x * 8 - + (short)((int)(DAT_BuildingsState::instance.buildings[sVar9].widthOrHeight * 8) / 2); - this->units[unitID].shootTargetMicroY = DAT_BuildingsState::instance.buildings[sVar9].y * 8 - + (short)((int)(DAT_BuildingsState::instance.buildings[sVar9].widthOrHeight * 8) / 2); - this->units[unitID].shootTargetZ = DAT_BuildingsState::instance.buildings[sVar9].terrainHeightUnk; + this->units[unitID].shootTargetMicroX = DAT_BuildingsState::instance.buildings[_buildingID].x * 8 + + (short)((int)(DAT_BuildingsState::instance.buildings[_buildingID].widthOrHeight * 8) / 2); + this->units[unitID].shootTargetMicroY = DAT_BuildingsState::instance.buildings[_buildingID].y * 8 + + (short)((int)(DAT_BuildingsState::instance.buildings[_buildingID].widthOrHeight * 8) / 2); + this->units[unitID].shootTargetZ + = DAT_BuildingsState::instance.buildings[_buildingID].terrainHeightUnk; this->units[unitID].shootTargetedUnit = -1; return TRUE; } @@ -222,9 +220,9 @@ namespace Map { int _0x17_y = (int)this->units[unitID].attackAtTileY; int _0x17_x = (int)this->units[unitID].attackAtTileX; int _0x17_tile = DAT_ViewportRenderState::instance.translationMatrix[_0x17_y].addXgetTile + _0x17_x; - BVar6 = MACRO_CALL_MEMBER(OpenSHC::Rendering::ViewportRenderState_Func::xyAreValid, + BOOLEnum _tileIsValid = MACRO_CALL_MEMBER(OpenSHC::Rendering::ViewportRenderState_Func::xyAreValid, DAT_ViewportRenderState::ptr)(_0x17_x, (uint)(_0x17_y)); - if (BVar6 != FALSE && (DAT_TileMapState::instance.LogicLayer[_0x17_tile] & 0x100U) != 0) { + if (_tileIsValid != FALSE && (DAT_TileMapState::instance.LogicLayer[_0x17_tile] & 0x100U) != 0) { this->units[unitID].shootTargetMicroX = this->units[unitID].attackAtTileX * 8; this->units[unitID].shootTargetMicroY = this->units[unitID].attackAtTileY * 8; this->units[unitID].shootTargetZ @@ -244,23 +242,24 @@ namespace Map { if (_entityType == 3) { return FALSE; } - for (int local_24 = 0; local_24 < DAT_GameState::instance.playerDataArray[_unitPlayerID].enemies; - local_24 = local_24 + 1) { - int _enemy = DAT_GameState::instance.playerDataArray[_unitPlayerID].enemyIDArray[local_24]; + for (int _enemyIndex = 0; + _enemyIndex < DAT_GameState::instance.playerDataArray[_unitPlayerID].enemies; + _enemyIndex = _enemyIndex + 1) { + int _enemy = DAT_GameState::instance.playerDataArray[_unitPlayerID].enemyIDArray[_enemyIndex]; if ((this->units[_enemy].dying != 0) || (this->units[_enemy].uid != DAT_GameState::instance.mapAndTime - .playerEnemenyUnitUIDShortList[_unitPlayerID][local_24])) + .playerEnemenyUnitUIDShortList[_unitPlayerID][_enemyIndex])) continue; switch (this->units[_enemy].unitType) { case OpenSHC::Map::Units::UT_ANTELOPESHDEER: if (this->units[unitID].unitType != OpenSHC::Map::Units::UT_HUNTER) continue; break; - case OpenSHC::Map::Units::UT_LIONSHWOLF: - sVar9 = this->units[_enemy].tribeID; - if (DAT_TribesState::instance.tribes[sVar9].unknownBool02 != 0 - || (DAT_TribesState::instance.tribes[sVar9].unknownBool01 == 0 + case OpenSHC::Map::Units::UT_LIONSHWOLF: { + short _enemyTribeID = this->units[_enemy].tribeID; + if (DAT_TribesState::instance.tribes[_enemyTribeID].unknownBool02 != 0 + || (DAT_TribesState::instance.tribes[_enemyTribeID].unknownBool01 == 0 && ((this->units[_enemy].state.generic != 0xcf || (this->units[this->units[_enemy] .targetedUnitID__OR__engineerMannedSiegeEngineRef] @@ -268,6 +267,7 @@ namespace Map { != 0))))) continue; break; + } case OpenSHC::Map::Units::UT_RABBIT: _xDifferenceToTarget = (int)this->units[unitID].tribeID; if (this->units[unitID].unitType == OpenSHC::Map::Units::UT_HUNTER @@ -285,9 +285,9 @@ namespace Map { continue; } _xDifferenceToTarget = (int)this->units[_enemy].microYPosition; - int iVar7 = (int)this->units[_enemy].microXPosition; + int _enemyMicroX = (int)this->units[_enemy].microXPosition; int _yDifferenceToTarget = ((int)_microYUnit / 8) - ((int)_xDifferenceToTarget / 8); - _xDifferenceToTarget = ((int)_microXUnit / 8) - ((int)iVar7 / 8); + _xDifferenceToTarget = (_microXUnit / 8) - (_enemyMicroX / 8); if (_rangeSquared < _xDifferenceToTarget * _xDifferenceToTarget + _yDifferenceToTarget * _yDifferenceToTarget) continue; @@ -297,11 +297,11 @@ namespace Map { } else { _xDifferenceToTarget = _xDifferenceToTarget - _microXUnit; } - iVar7 = (int)this->units[_enemy].microYPosition; - if (iVar7 < _microYUnit) { - _yDifferenceToTarget = _microYUnit - iVar7; + int _enemyMicroY = (int)this->units[_enemy].microYPosition; + if (_enemyMicroY < _microYUnit) { + _yDifferenceToTarget = _microYUnit - _enemyMicroY; } else { - _yDifferenceToTarget = iVar7 - _microYUnit; + _yDifferenceToTarget = _enemyMicroY - _microYUnit; } if (_xDifferenceToTarget < _yDifferenceToTarget) { _xDifferenceToTarget = _yDifferenceToTarget; @@ -451,23 +451,25 @@ namespace Map { _scoreNeedsValidityCheck = true; } if (!_scoreNeedsValidityCheck || _xDifferenceToTarget != -1) { - if (((_xDifferenceToTarget < local_30) || (_xDifferenceToTarget < local_2c)) - && (iVar7 + if (_xDifferenceToTarget < _bestScore || _xDifferenceToTarget < _bestUntargetedScore) { + int _shotFlightDistance = MACRO_CALL_MEMBER(OpenSHC::Map::Entities::EntityState_Func::arrowShootingRelated, DAT_EntityState::ptr)(_microXUnit, _microYUnit, _unitTotalHeight + 0x1e, - (int)(this->units[_enemy].microXPosition), iVar7, + (int)(this->units[_enemy].microXPosition), _enemyMicroY, (int)(this->units[_enemy].buildingHeight + 0x1a - + this->units[_enemy].terrainOrClimbHeight)), - 0 < iVar7)) { - if (_xDifferenceToTarget < local_30) { - local_30 = _xDifferenceToTarget; - _validTargetID = _enemy; - local_8 = iVar7; - } - if ((this->units[_enemy].field233_0x39a == 0) && (_xDifferenceToTarget < local_2c)) { - local_2c = _xDifferenceToTarget; - local_10 = _enemy; - local_c = iVar7; + + this->units[_enemy].terrainOrClimbHeight)); + if (_shotFlightDistance > 0) { + if (_xDifferenceToTarget < _bestScore) { + _bestScore = _xDifferenceToTarget; + _validTargetID = _enemy; + _shotDistance = _shotFlightDistance; + } + if (this->units[_enemy].field233_0x39a == 0 + && _xDifferenceToTarget < _bestUntargetedScore) { + _bestUntargetedScore = _xDifferenceToTarget; + _untargetedTargetID = _enemy; + _untargetedShotDistance = _shotFlightDistance; + } } } } @@ -475,9 +477,9 @@ namespace Map { if (_validTargetID == 0) { return FALSE; } - if ((local_10 != 0) && (local_2c < (local_30 * 3) / 2)) { - _validTargetID = local_10; - local_8 = local_c; + if ((_untargetedTargetID != 0) && (_bestUntargetedScore < (_bestScore * 3) / 2)) { + _validTargetID = _untargetedTargetID; + _shotDistance = _untargetedShotDistance; } if (_entityType == 4) { this->units[unitID].shootTargetedUnit = -2; @@ -486,22 +488,22 @@ namespace Map { this->units[unitID].shootTargetZ = this->units[_validTargetID].terrainOrClimbHeight; return TRUE; } - sVar9 = (short)_validTargetID; + short _chosenTargetID = (short)_validTargetID; if ((_entityType == 0x25) || (_entityType == 0x14)) { - this->units[unitID].shootTargetedUnit = sVar9; + this->units[unitID].shootTargetedUnit = _chosenTargetID; this->units[unitID].targetUID = this->units[_validTargetID].uid; - this->units[unitID].distanceToEnemyUnitLadders = (short)local_8; + this->units[unitID].distanceToEnemyUnitLadders = (short)_shotDistance; this->units[unitID].shootTargetMicroX = this->units[_validTargetID].microXPosition; this->units[unitID].shootTargetMicroY = this->units[_validTargetID].microYPosition; this->units[unitID].shootTargetZ = this->units[_validTargetID].terrainOrClimbHeight; return TRUE; } this->units[_validTargetID].field265_0x3dc = this->units[_validTargetID].field265_0x3dc + 1; - this->units[unitID].shootTargetedUnit = sVar9; - this->units[unitID].field266_0x3de = sVar9; + this->units[unitID].shootTargetedUnit = _chosenTargetID; + this->units[unitID].field266_0x3de = _chosenTargetID; this->units[unitID].targetUID = this->units[_validTargetID].uid; - this->units[unitID].distanceToEnemyUnitLadders = (short)local_8; - if (100 < local_8) { + this->units[unitID].distanceToEnemyUnitLadders = (short)_shotDistance; + if (100 < _shotDistance) { this->units[unitID].jugglerCount = 0; this->units[_validTargetID].field233_0x39a = 1; return TRUE; @@ -519,20 +521,20 @@ namespace Map { this->units[_validTargetID].field233_0x39a = 1; return TRUE; } - sVar9 = this->units[unitID].attackAtTileY; - short sVar5 = this->units[unitID].attackAtTileX; + short _attackTileY = this->units[unitID].attackAtTileY; + short _attackTileX = this->units[unitID].attackAtTileX; this->units[unitID].jugglerCount = -1; - BVar6 = MACRO_CALL_MEMBER(OpenSHC::Rendering::ViewportRenderState_Func::xyAreValid, - DAT_ViewportRenderState::ptr)((int)sVar5, (uint)(sVar9)); - if (BVar6 != FALSE) { - sVar5 = this->units[unitID].attackAtTileX; - this->units[unitID].shootTargetMicroX = sVar5 * 8; + BOOLEnum _tileIsValid = MACRO_CALL_MEMBER(OpenSHC::Rendering::ViewportRenderState_Func::xyAreValid, + DAT_ViewportRenderState::ptr)((int)_attackTileX, (uint)(_attackTileY)); + if (_tileIsValid != FALSE) { + _attackTileX = this->units[unitID].attackAtTileX; + this->units[unitID].shootTargetMicroX = _attackTileX * 8; this->units[unitID].shootTargetedUnit = -1; - this->units[unitID].shootTargetMicroY = sVar9 * 8; + this->units[unitID].shootTargetMicroY = _attackTileY * 8; this->units[unitID].shootTargetZ = (ushort)DAT_TileMapState::instance - .HeightLayer[DAT_ViewportRenderState::instance.translationMatrix[sVar9].addXgetTile - + (int)sVar5]; + .HeightLayer[DAT_ViewportRenderState::instance.translationMatrix[_attackTileY].addXgetTile + + (int)_attackTileX]; return TRUE; } } From f48a6f45c359246897a016c70ea0ac3ac89f9897 Mon Sep 17 00:00:00 2001 From: Gynt Date: Mon, 28 Sep 2026 14:49:29 +0200 Subject: [PATCH 287/299] reimplement: drop 60 field-walking pointers in updateUnits; 37.8% -> 39.0% "field += n" on a field the compiler already holds an address for comes back from the decompiler as a pointer and a store through it: piVar1 = &this->units[i].attackedBy; *piVar1 = *piVar1 + 1; MSVC regenerates the same instructions from the field form, and the project style asks for named fields rather than pointers walking over structs. unptr.py rewrites only the shape where the store immediately follows the pointer, which matters for more than simplicity: a pointer freezes the address while the field form re-evaluates the index. With nothing between the two lines the index cannot have changed. Where the decompiler sets a pointer up and dereferences it further down -- past a call, or past a write to the index -- the two forms can genuinely differ, so piVar1 and psVar4 are still declared for those. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01A4PvfebpUzaMXy93EutBjJ --- .../Map/Units/UnitsState/updateUnits.cpp | 306 +++++++++--------- 1 file changed, 160 insertions(+), 146 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/updateUnits.cpp b/src/OpenSHC/Map/Units/UnitsState/updateUnits.cpp index 12488ba8e..244ac6e1b 100644 --- a/src/OpenSHC/Map/Units/UnitsState/updateUnits.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/updateUnits.cpp @@ -206,11 +206,10 @@ namespace Map { if (this->units[DAT_CurrentUnitSlotID::instance].state.generic == OpenSHC::Map::Units::States::US_MELEE_ATTACK) { _buildingID = this->units[DAT_CurrentUnitSlotID::instance].attackedUnitID; - psVar4 = &this->units[_buildingID].attackedBy; - *psVar4 = *psVar4 + 1; + this->units[_buildingID].attackedBy = this->units[_buildingID].attackedBy + 1; if ((int)this->units[_buildingID].attackedUnitID != DAT_CurrentUnitSlotID::instance) { - psVar4 = &this->units[DAT_CurrentUnitSlotID::instance].attackedBy; - *psVar4 = *psVar4 + 1; + this->units[DAT_CurrentUnitSlotID::instance].attackedBy + = this->units[DAT_CurrentUnitSlotID::instance].attackedBy + 1; } if ((this->units[_buildingID].attackedBy == 1) && (this->units[_buildingID].isStalked == 0)) { @@ -220,13 +219,11 @@ namespace Map { } _buildingID = this->units[DAT_CurrentUnitSlotID::instance].movementType_OR_targetUnitID; if (_buildingID != 0) { - psVar4 = &this->units[_buildingID].huntedBy; - *psVar4 = *psVar4 + 1; + this->units[_buildingID].huntedBy = this->units[_buildingID].huntedBy + 1; } _buildingID = this->units[DAT_CurrentUnitSlotID::instance].field266_0x3de; if (_buildingID != 0) { - psVar4 = &this->units[_buildingID].field265_0x3dc; - *psVar4 = *psVar4 + 1; + this->units[_buildingID].field265_0x3dc = this->units[_buildingID].field265_0x3dc + 1; } psVar4 = &this->units[DAT_CurrentUnitSlotID::instance].field97_0xd0; if (0 < this->units[DAT_CurrentUnitSlotID::instance].field97_0xd0) { @@ -312,11 +309,12 @@ namespace Map { if (UVar6 != OpenSHC::Map::Units::UT_LORD) { short sVar7 = this->units[uVar9].aiUnitBehaviourType; if (sVar7 == 10) { - piVar1 = &DAT_GameState::instance.playerDataArray[_buildingID] - .totalAttackingEngineerTroops; - *piVar1 = *piVar1 + 1; - piVar1 = &DAT_GameState::instance.playerDataArray[_buildingID].totalAttackTroops; - *piVar1 = *piVar1 + 1; + DAT_GameState::instance.playerDataArray[_buildingID].totalAttackingEngineerTroops + = DAT_GameState::instance.playerDataArray[_buildingID] + .totalAttackingEngineerTroops + + 1; + DAT_GameState::instance.playerDataArray[_buildingID].totalAttackTroops + = DAT_GameState::instance.playerDataArray[_buildingID].totalAttackTroops + 1; } else if (UVar6 != OpenSHC::Map::Units::UT_E_ENGINEER) { /* fixme: TODO, review this bit, cannot be true! @@ -324,113 +322,118 @@ namespace Map { switch (sVar7) { case 0: - piVar1 = &DAT_GameState::instance.playerDataArray[_buildingID].totalTroopsType0; - *piVar1 = *piVar1 + 1; + DAT_GameState::instance.playerDataArray[_buildingID].totalTroopsType0 + = DAT_GameState::instance.playerDataArray[_buildingID].totalTroopsType0 + 1; break; case 1: case 4: - piVar1 = &DAT_GameState::instance.playerDataArray[_buildingID] - .totalDefensiveTroopsUnk; - *piVar1 = *piVar1 + 1; + DAT_GameState::instance.playerDataArray[_buildingID].totalDefensiveTroopsUnk + = DAT_GameState::instance.playerDataArray[_buildingID] + .totalDefensiveTroopsUnk + + 1; break; case 2: - piVar1 = &DAT_GameState::instance.playerDataArray[_buildingID] - .totalRaidingTroopsUnk; - *piVar1 = *piVar1 + 1; + DAT_GameState::instance.playerDataArray[_buildingID].totalRaidingTroopsUnk + = DAT_GameState::instance.playerDataArray[_buildingID].totalRaidingTroopsUnk + + 1; break; default: break; case 6: - piVar1 = &DAT_GameState::instance.playerDataArray[_buildingID].totalTroopsType6; - *piVar1 = *piVar1 + 1; + DAT_GameState::instance.playerDataArray[_buildingID].totalTroopsType6 + = DAT_GameState::instance.playerDataArray[_buildingID].totalTroopsType6 + 1; break; case 7: - piVar1 = &DAT_GameState::instance.playerDataArray[_buildingID].totalTroopsType7; - *piVar1 = *piVar1 + 1; + DAT_GameState::instance.playerDataArray[_buildingID].totalTroopsType7 + = DAT_GameState::instance.playerDataArray[_buildingID].totalTroopsType7 + 1; break; case 0xb: - piVar1 = &DAT_GameState::instance.playerDataArray[_buildingID] - .totalDiggingUnitTroops; - *piVar1 = *piVar1 + 1; - piVar1 - = &DAT_GameState::instance.playerDataArray[_buildingID].totalAttackTroops; - *piVar1 = *piVar1 + 1; + DAT_GameState::instance.playerDataArray[_buildingID].totalDiggingUnitTroops + = DAT_GameState::instance.playerDataArray[_buildingID] + .totalDiggingUnitTroops + + 1; + DAT_GameState::instance.playerDataArray[_buildingID].totalAttackTroops + = DAT_GameState::instance.playerDataArray[_buildingID].totalAttackTroops + + 1; break; case 0xc: - piVar1 - = &DAT_GameState::instance.playerDataArray[_buildingID].totalAssassinTroops; - *piVar1 = *piVar1 + 1; - piVar1 - = &DAT_GameState::instance.playerDataArray[_buildingID].totalAttackTroops; - *piVar1 = *piVar1 + 1; + DAT_GameState::instance.playerDataArray[_buildingID].totalAssassinTroops + = DAT_GameState::instance.playerDataArray[_buildingID].totalAssassinTroops + + 1; + DAT_GameState::instance.playerDataArray[_buildingID].totalAttackTroops + = DAT_GameState::instance.playerDataArray[_buildingID].totalAttackTroops + + 1; break; case 0xd: - piVar1 = &DAT_GameState::instance.playerDataArray[_buildingID].totalUnit2Troops; - *piVar1 = *piVar1 + 1; - piVar1 - = &DAT_GameState::instance.playerDataArray[_buildingID].totalAttackTroops; - *piVar1 = *piVar1 + 1; + DAT_GameState::instance.playerDataArray[_buildingID].totalUnit2Troops + = DAT_GameState::instance.playerDataArray[_buildingID].totalUnit2Troops + 1; + DAT_GameState::instance.playerDataArray[_buildingID].totalAttackTroops + = DAT_GameState::instance.playerDataArray[_buildingID].totalAttackTroops + + 1; break; case 0xe: - piVar1 = &DAT_GameState::instance.playerDataArray[_buildingID] - .totalLaddermenTroops; - *piVar1 = *piVar1 + 1; - piVar1 - = &DAT_GameState::instance.playerDataArray[_buildingID].totalAttackTroops; - *piVar1 = *piVar1 + 1; + DAT_GameState::instance.playerDataArray[_buildingID].totalLaddermenTroops + = DAT_GameState::instance.playerDataArray[_buildingID].totalLaddermenTroops + + 1; + DAT_GameState::instance.playerDataArray[_buildingID].totalAttackTroops + = DAT_GameState::instance.playerDataArray[_buildingID].totalAttackTroops + + 1; break; case 0xf: - piVar1 - = &DAT_GameState::instance.playerDataArray[_buildingID].totalTunnelerTroops; - *piVar1 = *piVar1 + 1; - piVar1 - = &DAT_GameState::instance.playerDataArray[_buildingID].totalAttackTroops; - *piVar1 = *piVar1 + 1; + DAT_GameState::instance.playerDataArray[_buildingID].totalTunnelerTroops + = DAT_GameState::instance.playerDataArray[_buildingID].totalTunnelerTroops + + 1; + DAT_GameState::instance.playerDataArray[_buildingID].totalAttackTroops + = DAT_GameState::instance.playerDataArray[_buildingID].totalAttackTroops + + 1; break; case 0x10: - piVar1 = &DAT_GameState::instance.playerDataArray[_buildingID] - .totalUnitPatrolTroops; - *piVar1 = *piVar1 + 1; - piVar1 - = &DAT_GameState::instance.playerDataArray[_buildingID].totalAttackTroops; - *piVar1 = *piVar1 + 1; + DAT_GameState::instance.playerDataArray[_buildingID].totalUnitPatrolTroops + = DAT_GameState::instance.playerDataArray[_buildingID].totalUnitPatrolTroops + + 1; + DAT_GameState::instance.playerDataArray[_buildingID].totalAttackTroops + = DAT_GameState::instance.playerDataArray[_buildingID].totalAttackTroops + + 1; break; case 0x11: - piVar1 = &DAT_GameState::instance.playerDataArray[_buildingID] - .totalUnitBackupTroops; - *piVar1 = *piVar1 + 1; - piVar1 - = &DAT_GameState::instance.playerDataArray[_buildingID].totalAttackTroops; - *piVar1 = *piVar1 + 1; + DAT_GameState::instance.playerDataArray[_buildingID].totalUnitBackupTroops + = DAT_GameState::instance.playerDataArray[_buildingID].totalUnitBackupTroops + + 1; + DAT_GameState::instance.playerDataArray[_buildingID].totalAttackTroops + = DAT_GameState::instance.playerDataArray[_buildingID].totalAttackTroops + + 1; break; case 0x12: - piVar1 = &DAT_GameState::instance.playerDataArray[_buildingID] - .totalUnitEngageTroops; - *piVar1 = *piVar1 + 1; - piVar1 - = &DAT_GameState::instance.playerDataArray[_buildingID].totalAttackTroops; - *piVar1 = *piVar1 + 1; + DAT_GameState::instance.playerDataArray[_buildingID].totalUnitEngageTroops + = DAT_GameState::instance.playerDataArray[_buildingID].totalUnitEngageTroops + + 1; + DAT_GameState::instance.playerDataArray[_buildingID].totalAttackTroops + = DAT_GameState::instance.playerDataArray[_buildingID].totalAttackTroops + + 1; break; case 0x13: - piVar1 = &DAT_GameState::instance.playerDataArray[_buildingID] - .totalUnitSiegeDefTroops; - *piVar1 = *piVar1 + 1; - piVar1 - = &DAT_GameState::instance.playerDataArray[_buildingID].totalAttackTroops; - *piVar1 = *piVar1 + 1; + DAT_GameState::instance.playerDataArray[_buildingID].totalUnitSiegeDefTroops + = DAT_GameState::instance.playerDataArray[_buildingID] + .totalUnitSiegeDefTroops + + 1; + DAT_GameState::instance.playerDataArray[_buildingID].totalAttackTroops + = DAT_GameState::instance.playerDataArray[_buildingID].totalAttackTroops + + 1; break; case 0x14: - piVar1 = &DAT_GameState::instance.playerDataArray[_buildingID] - .totalMaxDefaultTroops; - *piVar1 = *piVar1 + 1; - piVar1 - = &DAT_GameState::instance.playerDataArray[_buildingID].totalAttackTroops; - *piVar1 = *piVar1 + 1; + DAT_GameState::instance.playerDataArray[_buildingID].totalMaxDefaultTroops + = DAT_GameState::instance.playerDataArray[_buildingID].totalMaxDefaultTroops + + 1; + DAT_GameState::instance.playerDataArray[_buildingID].totalAttackTroops + = DAT_GameState::instance.playerDataArray[_buildingID].totalAttackTroops + + 1; break; case 0x15: - piVar1 = &DAT_GameState::instance.playerDataArray[_buildingID] - .harassingSiegeEnginesCountUnk; - *piVar1 = *piVar1 + 1; + DAT_GameState::instance.playerDataArray[_buildingID] + .harassingSiegeEnginesCountUnk + = DAT_GameState::instance.playerDataArray[_buildingID] + .harassingSiegeEnginesCountUnk + + 1; } } } @@ -480,8 +483,8 @@ namespace Map { if (DAT_TileMapState::instance.refreshRelatedOne != 0) { bVar13 = this->units[DAT_CurrentUnitSlotID::instance].heightDiv10; if (bVar13 != 0) { - undefined1* puVar2 = &this->units[DAT_CurrentUnitSlotID::instance].padding_0x83[0]; - *puVar2 = *puVar2 + this->units[DAT_CurrentUnitSlotID::instance].padding_0x83[0] + = this->units[DAT_CurrentUnitSlotID::instance].padding_0x83[0] - *(char*)((int)DAT_UnitPropertiesDefinedData::ptr + (DAT_UpdateUnitsTracker::instance - (uint)bVar13) * 4 + 0x11a24); if (100 < (byte)this->units[DAT_CurrentUnitSlotID::instance].padding_0x83[0]) { @@ -536,8 +539,8 @@ namespace Map { + this->units[DAT_CurrentUnitSlotID::instance].animationLeapTicksTotal < _animationTicker) { this->units[DAT_CurrentUnitSlotID::instance].animationLeapTicksTotal = _animationTicker; - piVar1 = &this->units[DAT_CurrentUnitSlotID::instance].animationCycleNumber; - *piVar1 = *piVar1 + 1; + this->units[DAT_CurrentUnitSlotID::instance].animationCycleNumber + = this->units[DAT_CurrentUnitSlotID::instance].animationCycleNumber + 1; this->units[DAT_CurrentUnitSlotID::instance].animationCycleNumberHasJustIncremented = TRUE; uVar9 = DAT_CurrentUnitSlotID::instance; if (999 < this->units[DAT_CurrentUnitSlotID::instance].animationCycleNumber) { @@ -566,12 +569,12 @@ namespace Map { } uVar9 = DAT_CurrentUnitSlotID::instance; _buildingID = this->units[DAT_CurrentUnitSlotID::instance].owner; - piVar1 = &DAT_GameState::instance.playerDataArray[_buildingID].countEntities; - *piVar1 = *piVar1 + 1; + DAT_GameState::instance.playerDataArray[_buildingID].countEntities + = DAT_GameState::instance.playerDataArray[_buildingID].countEntities + 1; if (DAT_UnitPropertiesDefinedData::instance.COMPUTER_MANAGED[(short)this->units[uVar9].unitType] != 0) { - piVar1 = &DAT_GameState::instance.playerDataArray[_buildingID].currentPopulation_2; - *piVar1 = *piVar1 + 1; + DAT_GameState::instance.playerDataArray[_buildingID].currentPopulation_2 + = DAT_GameState::instance.playerDataArray[_buildingID].currentPopulation_2 + 1; } DAT_UnitHasBecomeIdle::instance = 0; if (this->units[uVar9].dying != 0 @@ -654,8 +657,8 @@ namespace Map { || (UVar8 == OpenSHC::Map::Units::States::US_DIG)) && (_troopValue = this->units[DAT_CurrentUnitSlotID::instance].digTileTarget, DAT_TileMapState::instance.moats[_troopValue].owner != '\0')) { - char* pcVar3 = &DAT_TileMapState::instance.moats[_troopValue].someCountDown; - *pcVar3 = *pcVar3 + -0x14; + DAT_TileMapState::instance.moats[_troopValue].someCountDown + = DAT_TileMapState::instance.moats[_troopValue].someCountDown + -0x14; } this->units[uVar9].field41_0x5c = 0; if (this->units[DAT_CurrentUnitSlotID::instance].usingTeleport == 0) { @@ -687,34 +690,34 @@ namespace Map { && this->units[DAT_CurrentUnitSlotID::instance].fadeType == 0) { this->units[DAT_CurrentUnitSlotID::instance].disappearFadeAlphaCountdown = 0; } - psVar4 = &this->units[DAT_CurrentUnitSlotID::instance].field218_0x37e; - *psVar4 = *psVar4 + 1; + this->units[DAT_CurrentUnitSlotID::instance].field218_0x37e + = this->units[DAT_CurrentUnitSlotID::instance].field218_0x37e + 1; if (0xf < this->units[DAT_CurrentUnitSlotID::instance].field218_0x37e) { this->units[DAT_CurrentUnitSlotID::instance].field218_0x37e = 0; } - psVar4 = &this->units[DAT_CurrentUnitSlotID::instance].field217_0x37c; - *psVar4 = *psVar4 + 2; + this->units[DAT_CurrentUnitSlotID::instance].field217_0x37c + = this->units[DAT_CurrentUnitSlotID::instance].field217_0x37c + 2; if (0xd < this->units[DAT_CurrentUnitSlotID::instance].field217_0x37c) { this->units[DAT_CurrentUnitSlotID::instance].field217_0x37c = 0; } - psVar4 = &this->units[DAT_CurrentUnitSlotID::instance].field215_0x378; - *psVar4 = *psVar4 + 2; + this->units[DAT_CurrentUnitSlotID::instance].field215_0x378 + = this->units[DAT_CurrentUnitSlotID::instance].field215_0x378 + 2; if (0xf < this->units[DAT_CurrentUnitSlotID::instance].field215_0x378) { this->units[DAT_CurrentUnitSlotID::instance].field215_0x378 = 0; } - psVar4 = &this->units[DAT_CurrentUnitSlotID::instance].field254_0x3c6; - *psVar4 = *psVar4 + 1; + this->units[DAT_CurrentUnitSlotID::instance].field254_0x3c6 + = this->units[DAT_CurrentUnitSlotID::instance].field254_0x3c6 + 1; if (0x11 < this->units[DAT_CurrentUnitSlotID::instance].field254_0x3c6) { this->units[DAT_CurrentUnitSlotID::instance].field254_0x3c6 = 0; } - psVar4 = &this->units[DAT_CurrentUnitSlotID::instance].field312_0x428; - *psVar4 = *psVar4 + 1; + this->units[DAT_CurrentUnitSlotID::instance].field312_0x428 + = this->units[DAT_CurrentUnitSlotID::instance].field312_0x428 + 1; if (0x17 < this->units[DAT_CurrentUnitSlotID::instance].field312_0x428) { this->units[DAT_CurrentUnitSlotID::instance].field312_0x428 = 0; } } - psVar4 = &this->units[DAT_CurrentUnitSlotID::instance].field216_0x37a; - *psVar4 = *psVar4 + 1; + this->units[DAT_CurrentUnitSlotID::instance].field216_0x37a + = this->units[DAT_CurrentUnitSlotID::instance].field216_0x37a + 1; if (0xb < this->units[DAT_CurrentUnitSlotID::instance].field216_0x37a) { this->units[DAT_CurrentUnitSlotID::instance].field216_0x37a = 0; } @@ -737,8 +740,9 @@ namespace Map { = (int)this->units[DAT_CurrentUnitSlotID::instance] .facingDirectionMapOrientationCorrected + this->units[DAT_CurrentUnitSlotID::instance].animationSheetFrameOffset; - piVar1 = &this->units[DAT_CurrentUnitSlotID::instance].gfxNumber; - *piVar1 = *piVar1 + this->units[DAT_CurrentUnitSlotID::instance].field215_0x378 * 8; + this->units[DAT_CurrentUnitSlotID::instance].gfxNumber + = this->units[DAT_CurrentUnitSlotID::instance].gfxNumber + + this->units[DAT_CurrentUnitSlotID::instance].field215_0x378 * 8; if (this->units[DAT_CurrentUnitSlotID::instance].unitType == OpenSHC::Map::Units::UT_A_HARCHER && (_buildingID @@ -754,32 +758,36 @@ namespace Map { = (int)this->units[DAT_CurrentUnitSlotID::instance] .facingDirectionMapOrientationCorrected + this->units[DAT_CurrentUnitSlotID::instance].animationSheetFrameOffset; - piVar1 = &this->units[DAT_CurrentUnitSlotID::instance].gfxNumber; - *piVar1 = *piVar1 + (this->units[DAT_CurrentUnitSlotID::instance].field215_0x378 * 8) / 2; + this->units[DAT_CurrentUnitSlotID::instance].gfxNumber + = this->units[DAT_CurrentUnitSlotID::instance].gfxNumber + + (this->units[DAT_CurrentUnitSlotID::instance].field215_0x378 * 8) / 2; break; case 0xc: this->units[DAT_CurrentUnitSlotID::instance].gfxNumber = (int)this->units[DAT_CurrentUnitSlotID::instance] .facingDirectionMapOrientationCorrected + this->units[DAT_CurrentUnitSlotID::instance].animationSheetFrameOffset; - piVar1 = &this->units[DAT_CurrentUnitSlotID::instance].gfxNumber; - *piVar1 = *piVar1 + this->units[DAT_CurrentUnitSlotID::instance].field216_0x37a * 8; + this->units[DAT_CurrentUnitSlotID::instance].gfxNumber + = this->units[DAT_CurrentUnitSlotID::instance].gfxNumber + + this->units[DAT_CurrentUnitSlotID::instance].field216_0x37a * 8; break; case 0xe: this->units[DAT_CurrentUnitSlotID::instance].gfxNumber = (int)this->units[DAT_CurrentUnitSlotID::instance] .facingDirectionMapOrientationCorrected + this->units[DAT_CurrentUnitSlotID::instance].animationSheetFrameOffset; - piVar1 = &this->units[DAT_CurrentUnitSlotID::instance].gfxNumber; - *piVar1 = *piVar1 + this->units[DAT_CurrentUnitSlotID::instance].field217_0x37c * 8; + this->units[DAT_CurrentUnitSlotID::instance].gfxNumber + = this->units[DAT_CurrentUnitSlotID::instance].gfxNumber + + this->units[DAT_CurrentUnitSlotID::instance].field217_0x37c * 8; break; case 0x10: this->units[DAT_CurrentUnitSlotID::instance].gfxNumber = (int)this->units[DAT_CurrentUnitSlotID::instance] .facingDirectionMapOrientationCorrected + this->units[DAT_CurrentUnitSlotID::instance].animationSheetFrameOffset; - piVar1 = &this->units[DAT_CurrentUnitSlotID::instance].gfxNumber; - *piVar1 = *piVar1 + this->units[DAT_CurrentUnitSlotID::instance].field218_0x37e * 8; + this->units[DAT_CurrentUnitSlotID::instance].gfxNumber + = this->units[DAT_CurrentUnitSlotID::instance].gfxNumber + + this->units[DAT_CurrentUnitSlotID::instance].field218_0x37e * 8; if (this->units[DAT_CurrentUnitSlotID::instance].unitType == OpenSHC::Map::Units::UT_A_HARCHER) { this->units[DAT_CurrentUnitSlotID::instance].imageIDUnk @@ -798,12 +806,12 @@ namespace Map { && this->units[DAT_CurrentUnitSlotID::instance].totalSizeOfPathPlan + -0x10 <= (int)this->units[DAT_CurrentUnitSlotID::instance] .currentIndexInPathPlan) { - piVar1 = &this->units[DAT_CurrentUnitSlotID::instance].imageIDUnk; - *piVar1 = *piVar1 + 0x80; + this->units[DAT_CurrentUnitSlotID::instance].imageIDUnk + = this->units[DAT_CurrentUnitSlotID::instance].imageIDUnk + 0x80; } } else { - piVar1 = &this->units[DAT_CurrentUnitSlotID::instance].imageIDUnk; - *piVar1 = *piVar1 + 0x270; + this->units[DAT_CurrentUnitSlotID::instance].imageIDUnk + = this->units[DAT_CurrentUnitSlotID::instance].imageIDUnk + 0x270; } } break; @@ -812,16 +820,18 @@ namespace Map { = this->units[DAT_CurrentUnitSlotID::instance].facingDirectionMapOrientationCorrected * 0x10 + this->units[DAT_CurrentUnitSlotID::instance].animationSheetFrameOffset; - piVar1 = &this->units[DAT_CurrentUnitSlotID::instance].gfxNumber; - *piVar1 = *piVar1 + (int)this->units[DAT_CurrentUnitSlotID::instance].field218_0x37e; + this->units[DAT_CurrentUnitSlotID::instance].gfxNumber + = this->units[DAT_CurrentUnitSlotID::instance].gfxNumber + + (int)this->units[DAT_CurrentUnitSlotID::instance].field218_0x37e; break; case 0x12: this->units[DAT_CurrentUnitSlotID::instance].gfxNumber = (int)this->units[DAT_CurrentUnitSlotID::instance] .facingDirectionMapOrientationCorrected + this->units[DAT_CurrentUnitSlotID::instance].animationSheetFrameOffset; - piVar1 = &this->units[DAT_CurrentUnitSlotID::instance].gfxNumber; - *piVar1 = *piVar1 + this->units[DAT_CurrentUnitSlotID::instance].field254_0x3c6 * 8; + this->units[DAT_CurrentUnitSlotID::instance].gfxNumber + = this->units[DAT_CurrentUnitSlotID::instance].gfxNumber + + this->units[DAT_CurrentUnitSlotID::instance].field254_0x3c6 * 8; break; case 0x13: case 0x14: @@ -829,23 +839,25 @@ namespace Map { = (int)this->units[DAT_CurrentUnitSlotID::instance] .facingDirectionMapOrientationCorrected + this->units[DAT_CurrentUnitSlotID::instance].animationSheetFrameOffset; - piVar1 = &this->units[DAT_CurrentUnitSlotID::instance].imageIDUnk; - *piVar1 - = *piVar1 + ((int)this->units[DAT_CurrentUnitSlotID::instance].field215_0x378 / 2) * 8; + this->units[DAT_CurrentUnitSlotID::instance].imageIDUnk + = this->units[DAT_CurrentUnitSlotID::instance].imageIDUnk + + ((int)this->units[DAT_CurrentUnitSlotID::instance].field215_0x378 / 2) * 8; break; case 0x15: this->units[DAT_CurrentUnitSlotID::instance].gfxNumber = (int)this->units[DAT_CurrentUnitSlotID::instance] .facingDirectionMapOrientationCorrected + this->units[DAT_CurrentUnitSlotID::instance].animationSheetFrameOffset; - piVar1 = &this->units[DAT_CurrentUnitSlotID::instance].gfxNumber; - *piVar1 = *piVar1 + this->units[DAT_CurrentUnitSlotID::instance].field218_0x37e * 8; + this->units[DAT_CurrentUnitSlotID::instance].gfxNumber + = this->units[DAT_CurrentUnitSlotID::instance].gfxNumber + + this->units[DAT_CurrentUnitSlotID::instance].field218_0x37e * 8; _troopValue = this->units[DAT_CurrentUnitSlotID::instance].facingDirectionMapOrientationCorrected + 0x80 + this->units[DAT_CurrentUnitSlotID::instance].animationSheetFrameOffset; this->units[DAT_CurrentUnitSlotID::instance].imageIDUnk = _troopValue; - piVar1 = &this->units[DAT_CurrentUnitSlotID::instance].imageIDUnk; - *piVar1 = *piVar1 + this->units[DAT_CurrentUnitSlotID::instance].field218_0x37e * 8; + this->units[DAT_CurrentUnitSlotID::instance].imageIDUnk + = this->units[DAT_CurrentUnitSlotID::instance].imageIDUnk + + this->units[DAT_CurrentUnitSlotID::instance].field218_0x37e * 8; break; case 0x16: uVar9 = ((int)this->units[DAT_CurrentUnitSlotID::instance] @@ -853,34 +865,36 @@ namespace Map { + 4) % 8; this->units[DAT_CurrentUnitSlotID::instance].gfxNumber = uVar9 + 0x151; - piVar1 = &this->units[DAT_CurrentUnitSlotID::instance].gfxNumber; - *piVar1 - = *piVar1 + ((byte)this->units[DAT_CurrentUnitSlotID::instance].field218_0x37e & 3) * 8; + this->units[DAT_CurrentUnitSlotID::instance].gfxNumber + = this->units[DAT_CurrentUnitSlotID::instance].gfxNumber + + ((byte)this->units[DAT_CurrentUnitSlotID::instance].field218_0x37e & 3) * 8; uVar9 = ((int)this->units[DAT_CurrentUnitSlotID::instance] .facingDirectionMapOrientationCorrected + 4) % 8; _troopValue = uVar9 + 0x1d1; this->units[DAT_CurrentUnitSlotID::instance].imageIDUnk = _troopValue; - piVar1 = &this->units[DAT_CurrentUnitSlotID::instance].imageIDUnk; - *piVar1 = *piVar1 + this->units[DAT_CurrentUnitSlotID::instance].field218_0x37e * 8; + this->units[DAT_CurrentUnitSlotID::instance].imageIDUnk + = this->units[DAT_CurrentUnitSlotID::instance].imageIDUnk + + this->units[DAT_CurrentUnitSlotID::instance].field218_0x37e * 8; break; case 0x18: this->units[DAT_CurrentUnitSlotID::instance].gfxNumber = (int)this->units[DAT_CurrentUnitSlotID::instance] .facingDirectionMapOrientationCorrected + this->units[DAT_CurrentUnitSlotID::instance].animationSheetFrameOffset; - piVar1 = &this->units[DAT_CurrentUnitSlotID::instance].gfxNumber; - *piVar1 = *piVar1 + this->units[DAT_CurrentUnitSlotID::instance].field312_0x428 * 8; + this->units[DAT_CurrentUnitSlotID::instance].gfxNumber + = this->units[DAT_CurrentUnitSlotID::instance].gfxNumber + + this->units[DAT_CurrentUnitSlotID::instance].field312_0x428 * 8; break; case 99: this->units[DAT_CurrentUnitSlotID::instance].imageID2 = (int)this->units[DAT_CurrentUnitSlotID::instance] .facingDirectionMapOrientationCorrected + this->units[DAT_CurrentUnitSlotID::instance].animationSheetFrameOffset; - piVar1 = &this->units[DAT_CurrentUnitSlotID::instance].imageID2; - *piVar1 - = *piVar1 + ((int)this->units[DAT_CurrentUnitSlotID::instance].field215_0x378 / 2) * 8; + this->units[DAT_CurrentUnitSlotID::instance].imageID2 + = this->units[DAT_CurrentUnitSlotID::instance].imageID2 + + ((int)this->units[DAT_CurrentUnitSlotID::instance].field215_0x378 / 2) * 8; } psVar4 = &this->units[DAT_CurrentUnitSlotID::instance].unitSpeedMatchingRelatedUnk; if (this->units[DAT_CurrentUnitSlotID::instance].unitSpeedMatchingRelatedUnk != 0) { @@ -908,8 +922,8 @@ namespace Map { } this->units[DAT_CurrentUnitSlotID::instance].disappearFadeAlphaCountdown = bVar13; } - byte* pbVar11 = &this->units[DAT_CurrentUnitSlotID::instance].fadeCounter; - *pbVar11 = *pbVar11 + 1; + this->units[DAT_CurrentUnitSlotID::instance].fadeCounter + = this->units[DAT_CurrentUnitSlotID::instance].fadeCounter + 1; if ((char)this->units[DAT_CurrentUnitSlotID::instance].disappearFadeAlphaCountdown < '\x01') { this->units[DAT_CurrentUnitSlotID::instance].fadeType = 0; From 3883cb42a62e74e237d997e6bfc42141f912678c Mon Sep 17 00:00:00 2001 From: Gynt Date: Mon, 28 Sep 2026 21:57:17 +0200 Subject: [PATCH 288/299] reimplement: updateUnits reads the unit slot global directly; 39.0% -> 40.9% The decompiler reloads uVar9 from DAT_CurrentUnitSlotID::instance eighteen times, every one of them just after a call. A source-level local would give one load; a reload at each point where a call could have clobbered the register means the source read the global directly and the compiler cached it in between. Reading it directly is worth 1.9%, and normalized 38.0% -> 41.5%. uVar9 also held two unrelated values -- a target x, and the facing direction taken mod 8 in case 0x16 -- and bVar13 held three unrelated bytes: a height, a fade type, and the alpha it maps to. Those are split. No decompiler- generated names are left in this function. The nine remaining field-walking pointers stay, and they are worth a remark. All nine are the set-up-then-use-later shape unptr.py skips, and all nine were checked by hand as safe to remove: no index can change in between, and the one with a call between the setup and the store takes its address from a local and a fixed global base. Removing them anyway measured 2.7% worse (38.4% against 41.1%), so where the dereference is separated from its setup the original really did hold a pointer. unptr.py''s adjacent-lines-only rule was chosen for safety but turns out to be the right line for matching too: the adjacent shape gained 1.2% over 60 sites, this one loses. They are named _intFieldPtr and _shortFieldPtr rather than deleted. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01A4PvfebpUzaMXy93EutBjJ --- .../Map/Units/UnitsState/updateUnits.cpp | 232 +++++++++--------- 1 file changed, 113 insertions(+), 119 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/updateUnits.cpp b/src/OpenSHC/Map/Units/UnitsState/updateUnits.cpp index 244ac6e1b..cd9aa5743 100644 --- a/src/OpenSHC/Map/Units/UnitsState/updateUnits.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/updateUnits.cpp @@ -49,13 +49,11 @@ namespace Map { void UnitsState::updateUnits() { - int* piVar1; - short* psVar4; + int* _intFieldPtr; + short* _shortFieldPtr; UnitTypeShort UVar6; uint _unitIDBased8value; - uint uVar9; int _troopValue; - byte bVar13; uint _rngNumber8; uint _unitID; uint _currentUnitID; @@ -92,11 +90,10 @@ namespace Map { hell? */ - psVar4 = &this->units[DAT_CurrentUnitSlotID::instance].targetShootRelated; + _shortFieldPtr = &this->units[DAT_CurrentUnitSlotID::instance].targetShootRelated; if (this->units[DAT_CurrentUnitSlotID::instance].targetShootRelated != 0) { - *psVar4 = *psVar4 + -1; + *_shortFieldPtr = *_shortFieldPtr + -1; } - uVar9 = DAT_CurrentUnitSlotID::instance; if ((this->units[DAT_CurrentUnitSlotID::instance].state.generic == OpenSHC::Map::Units::States::US_DETERMINE_NEXT_STATEUnk) && (_troopValue @@ -105,14 +102,13 @@ namespace Map { _troopValue == 0)) { this->lostChimps = this->lostChimps + 1; this->units[DAT_CurrentUnitSlotID::instance].logicalState = OpenSHC::Map::Units::ULS_REMOVE; - uVar9 = DAT_CurrentUnitSlotID::instance; } - _buildingID = this->units[uVar9].owner; + _buildingID = this->units[DAT_CurrentUnitSlotID::instance].owner; if (DAT_GameSynchronyState::instance.currentPlayerFullIDArray[_buildingID] == -1) { - this->units[uVar9].siegeTargetPlayerID + this->units[DAT_CurrentUnitSlotID::instance].siegeTargetPlayerID = (short)DAT_GameState::instance.playerDataArray[_buildingID].attackedPlayerID; } else { - this->units[uVar9].siegeTargetPlayerID = 0; + this->units[DAT_CurrentUnitSlotID::instance].siegeTargetPlayerID = 0; } if (this->units[DAT_CurrentUnitSlotID::instance].blessedAmount != 0) { this->units[DAT_CurrentUnitSlotID::instance].blessedAmount @@ -155,15 +151,15 @@ namespace Map { && (_unitType = this->units[_currentUnitID].unitType, _unitType != OpenSHC::Map::Units::UT_S_TOWER)) { if (_unitType == OpenSHC::Map::Units::UT_LORD) { - uint uVar12 = (uint)this->units[_currentUnitID].targetY_2; - uVar9 = (uint)this->units[_currentUnitID].targetX_2; + uint _targetY = (uint)this->units[_currentUnitID].targetY_2; + uint _targetX = (uint)this->units[_currentUnitID].targetX_2; MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::setPositionOfUnit, - this)(_currentUnitID, uVar9, uVar12, + this)(_currentUnitID, _targetX, _targetY, (undefined4)((int)(DAT_TileMapState::instance .HeightLayer[DAT_ViewportRenderState::instance - .translationMatrix[uVar12] + .translationMatrix[_targetY] .addXgetTile - + uVar9]))); + + _targetX]))); this->units[DAT_CurrentUnitSlotID::instance].state.generic = OpenSHC::Map::Units::States::US_IDLEUnk; this->units[DAT_CurrentUnitSlotID::instance].destinationNeeded @@ -225,9 +221,9 @@ namespace Map { if (_buildingID != 0) { this->units[_buildingID].field265_0x3dc = this->units[_buildingID].field265_0x3dc + 1; } - psVar4 = &this->units[DAT_CurrentUnitSlotID::instance].field97_0xd0; + _shortFieldPtr = &this->units[DAT_CurrentUnitSlotID::instance].field97_0xd0; if (0 < this->units[DAT_CurrentUnitSlotID::instance].field97_0xd0) { - *psVar4 = *psVar4 + -1; + *_shortFieldPtr = *_shortFieldPtr + -1; } } DAT_CurrentUnitSlotID::instance = DAT_CurrentUnitSlotID::instance + 1; @@ -272,20 +268,19 @@ namespace Map { OpenSHC::Map::Units::UnitsState_Func::stampOccupancyFlagOnSurroundingTiles, this)( DAT_CurrentUnitSlotID::instance); } - uVar9 = DAT_CurrentUnitSlotID::instance; DAT_TileMapState::instance.OccupancyLayer[this->units[DAT_CurrentUnitSlotID::instance].tile] = DAT_TileMapState::instance .OccupancyLayer[this->units[DAT_CurrentUnitSlotID::instance].tile] | this->units[DAT_CurrentUnitSlotID::instance].occupancyOrFlag; - if (this->units[uVar9].isSelectable_OR_matchTime != 0) { - _buildingID = this->units[uVar9].owner; + if (this->units[DAT_CurrentUnitSlotID::instance].isSelectable_OR_matchTime != 0) { + _buildingID = this->units[DAT_CurrentUnitSlotID::instance].owner; if ((DAT_GameCore::instance.mapTimeInTicks & 0x3f) == 0) { - piVar1 = &DAT_GameState::instance.playerDataArray[_buildingID].totalTroopValue; + _intFieldPtr = &DAT_GameState::instance.playerDataArray[_buildingID].totalTroopValue; _troopValue = MACRO_CALL_MEMBER(OpenSHC::Map::Units::TroopValueState_Func::getValueOfTroopType, - DAT_TroopValueState::ptr)((UnitType)(short)this->units[uVar9].unitType); - *piVar1 = *piVar1 + _troopValue; - uVar9 = DAT_CurrentUnitSlotID::instance; + DAT_TroopValueState::ptr)( + (UnitType)(short)this->units[DAT_CurrentUnitSlotID::instance].unitType); + *_intFieldPtr = *_intFieldPtr + _troopValue; if ((char)this->units[DAT_CurrentUnitSlotID::instance].firstNameIndex < '\x01') { /* Every 0x3f ticks, assign names to citizen units @@ -293,22 +288,21 @@ namespace Map { MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::assignNameToUnit, this)( DAT_CurrentUnitSlotID::instance); - uVar9 = DAT_CurrentUnitSlotID::instance; } } - UVar6 = this->units[uVar9].unitType; + UVar6 = this->units[DAT_CurrentUnitSlotID::instance].unitType; if (UVar6 == OpenSHC::Map::Units::UT_A_HARCHER) { - DAT_TileMapState::instance.SEC_TileMap1104[this->units[uVar9].tile] = '\x06'; + DAT_TileMapState::instance + .SEC_TileMap1104[this->units[DAT_CurrentUnitSlotID::instance].tile] = '\x06'; } else if (UVar6 == OpenSHC::Map::Units::UT_A_FIRETHROWER) { MACRO_CALL_MEMBER( OpenSHC::Map::Units::UnitsState_Func::writeSixToTileMap1104InAllDirections, this)( - uVar9, 6); - uVar9 = DAT_CurrentUnitSlotID::instance; + DAT_CurrentUnitSlotID::instance, 6); } - UVar6 = this->units[uVar9].unitType; + UVar6 = this->units[DAT_CurrentUnitSlotID::instance].unitType; if (UVar6 != OpenSHC::Map::Units::UT_LORD) { - short sVar7 = this->units[uVar9].aiUnitBehaviourType; - if (sVar7 == 10) { + short _aiBehaviour = this->units[DAT_CurrentUnitSlotID::instance].aiUnitBehaviourType; + if (_aiBehaviour == 10) { DAT_GameState::instance.playerDataArray[_buildingID].totalAttackingEngineerTroops = DAT_GameState::instance.playerDataArray[_buildingID] .totalAttackingEngineerTroops @@ -320,7 +314,7 @@ namespace Map { fixme: TODO, review this bit, cannot be true! */ - switch (sVar7) { + switch (_aiBehaviour) { case 0: DAT_GameState::instance.playerDataArray[_buildingID].totalTroopsType0 = DAT_GameState::instance.playerDataArray[_buildingID].totalTroopsType0 + 1; @@ -438,55 +432,57 @@ namespace Map { } } } - _buildingID = this->units[uVar9].unitType; + _buildingID = this->units[DAT_CurrentUnitSlotID::instance].unitType; if (((_buildingID == OpenSHC::Map::Units::UT_E_ARCHER) || (_buildingID == OpenSHC::Map::Units::UT_A_ARCHER)) - && (_buildingID = this->units[uVar9].state.generic, + && (_buildingID = this->units[DAT_CurrentUnitSlotID::instance].state.generic, _buildingID == OpenSHC::Map::Units::States::US_AIM_WEAPONUnk || (_buildingID == OpenSHC::Map::Units::States::US_FIRE_WEAPONUnk)) - && (_troopValue = this->units[uVar9].shootTargetedUnit, - 0 < _troopValue && (this->units[_troopValue].uid == this->units[uVar9].targetUID))) { + && (_troopValue = this->units[DAT_CurrentUnitSlotID::instance].shootTargetedUnit, + 0 < _troopValue + && (this->units[_troopValue].uid + == this->units[DAT_CurrentUnitSlotID::instance].targetUID))) { this->units[_troopValue].field233_0x39a = 1; - uVar9 = DAT_CurrentUnitSlotID::instance; } - if (this->units[uVar9].enemyNoticeFrequencyUnk != 0 + if (this->units[DAT_CurrentUnitSlotID::instance].enemyNoticeFrequencyUnk != 0 && (DAT_GameState::instance.mapAndTime.totalGameTicksUnk - & this->units[uVar9].enemyNoticeFrequencyUnk) - == (this->units[uVar9].fixedRng & this->units[uVar9].enemyNoticeFrequencyUnk)) { - if (this->units[uVar9].owner == 0) { + & this->units[DAT_CurrentUnitSlotID::instance].enemyNoticeFrequencyUnk) + == (this->units[DAT_CurrentUnitSlotID::instance].fixedRng + & this->units[DAT_CurrentUnitSlotID::instance].enemyNoticeFrequencyUnk)) { + if (this->units[DAT_CurrentUnitSlotID::instance].owner == 0) { _troopValue = MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func:: computeDistanceToNearestEnemyForLegacyMissions, - this)(uVar9); - this->units[uVar9].closestEnemyMicroDistance = (short)_troopValue; - uVar9 = DAT_CurrentUnitSlotID::instance; + this)(DAT_CurrentUnitSlotID::instance); + this->units[DAT_CurrentUnitSlotID::instance].closestEnemyMicroDistance + = (short)_troopValue; } else { - dword dVar10 = MACRO_CALL_MEMBER( + dword _closestEnemyDistance = MACRO_CALL_MEMBER( OpenSHC::Map::Units::UnitsState_Func::findNearestEnemyAndHeadTowardsIt, this)( - uVar9); - this->units[DAT_CurrentUnitSlotID::instance].closestEnemyMicroDistance = (short)dVar10; + DAT_CurrentUnitSlotID::instance); + this->units[DAT_CurrentUnitSlotID::instance].closestEnemyMicroDistance + = (short)_closestEnemyDistance; this->units[DAT_CurrentUnitSlotID::instance].assassinsMicroDistanceToEnemyUnk = this->unitDistanceComputationResultUnk; - uVar9 = DAT_CurrentUnitSlotID::instance; } } - psVar4 = &this->units[uVar9].lookForEnemy; - if (this->units[uVar9].lookForEnemy < 0) { - *psVar4 = *psVar4 + 1; + _shortFieldPtr = &this->units[DAT_CurrentUnitSlotID::instance].lookForEnemy; + if (this->units[DAT_CurrentUnitSlotID::instance].lookForEnemy < 0) { + *_shortFieldPtr = *_shortFieldPtr + 1; } else { - *psVar4 = 0; + *_shortFieldPtr = 0; } - psVar4 = &this->units[DAT_CurrentUnitSlotID::instance].unknownMovementRelated_0x2d2; + _shortFieldPtr = &this->units[DAT_CurrentUnitSlotID::instance].unknownMovementRelated_0x2d2; if (this->units[DAT_CurrentUnitSlotID::instance].unknownMovementRelated_0x2d2 < 0) { - *psVar4 = *psVar4 + 1; + *_shortFieldPtr = *_shortFieldPtr + 1; } this->units[DAT_CurrentUnitSlotID::instance].SA = 0; if (DAT_TileMapState::instance.refreshRelatedOne != 0) { - bVar13 = this->units[DAT_CurrentUnitSlotID::instance].heightDiv10; - if (bVar13 != 0) { + byte _heightDiv10 = this->units[DAT_CurrentUnitSlotID::instance].heightDiv10; + if (_heightDiv10 != 0) { this->units[DAT_CurrentUnitSlotID::instance].padding_0x83[0] = this->units[DAT_CurrentUnitSlotID::instance].padding_0x83[0] - *(char*)((int)DAT_UnitPropertiesDefinedData::ptr - + (DAT_UpdateUnitsTracker::instance - (uint)bVar13) * 4 + 0x11a24); + + (DAT_UpdateUnitsTracker::instance - (uint)_heightDiv10) * 4 + 0x11a24); if (100 < (byte)this->units[DAT_CurrentUnitSlotID::instance].padding_0x83[0]) { this->units[DAT_CurrentUnitSlotID::instance].padding_0x83[0] = 0; } @@ -542,64 +538,65 @@ namespace Map { this->units[DAT_CurrentUnitSlotID::instance].animationCycleNumber = this->units[DAT_CurrentUnitSlotID::instance].animationCycleNumber + 1; this->units[DAT_CurrentUnitSlotID::instance].animationCycleNumberHasJustIncremented = TRUE; - uVar9 = DAT_CurrentUnitSlotID::instance; if (999 < this->units[DAT_CurrentUnitSlotID::instance].animationCycleNumber) { this->units[DAT_CurrentUnitSlotID::instance].animationCycleNumber = 0; } } else { this->units[DAT_CurrentUnitSlotID::instance].animationCycleNumberHasJustIncremented = FALSE; - uVar9 = DAT_CurrentUnitSlotID::instance; } _buildingID = (short)DAT_TileMapState::instance.mapOrientation; - if (this->units[uVar9].field39_0x58 == 0) { - if (this->units[uVar9].state.generic != OpenSHC::Map::Units::States::US_MELEE_ATTACK) { - this->units[uVar9].facingDirectionMapOrientationCorrected - = this->units[uVar9].facingDirection - _buildingID; + if (this->units[DAT_CurrentUnitSlotID::instance].field39_0x58 == 0) { + if (this->units[DAT_CurrentUnitSlotID::instance].state.generic + != OpenSHC::Map::Units::States::US_MELEE_ATTACK) { + this->units[DAT_CurrentUnitSlotID::instance].facingDirectionMapOrientationCorrected + = this->units[DAT_CurrentUnitSlotID::instance].facingDirection - _buildingID; } else { - this->units[uVar9].facingDirectionMapOrientationCorrected - = this->units[uVar9].orientation - _buildingID; + this->units[DAT_CurrentUnitSlotID::instance].facingDirectionMapOrientationCorrected + = this->units[DAT_CurrentUnitSlotID::instance].orientation - _buildingID; } } else { - this->units[uVar9].facingDirectionMapOrientationCorrected + this->units[DAT_CurrentUnitSlotID::instance].facingDirectionMapOrientationCorrected = (short)DAT_TileMapState::instance.field84_0x5548a4 - _buildingID; } - psVar4 = &this->units[DAT_CurrentUnitSlotID::instance].facingDirectionMapOrientationCorrected; + _shortFieldPtr + = &this->units[DAT_CurrentUnitSlotID::instance].facingDirectionMapOrientationCorrected; if (this->units[DAT_CurrentUnitSlotID::instance].facingDirectionMapOrientationCorrected < 0) { - *psVar4 = *psVar4 + 8; + *_shortFieldPtr = *_shortFieldPtr + 8; } - uVar9 = DAT_CurrentUnitSlotID::instance; _buildingID = this->units[DAT_CurrentUnitSlotID::instance].owner; DAT_GameState::instance.playerDataArray[_buildingID].countEntities = DAT_GameState::instance.playerDataArray[_buildingID].countEntities + 1; - if (DAT_UnitPropertiesDefinedData::instance.COMPUTER_MANAGED[(short)this->units[uVar9].unitType] + if (DAT_UnitPropertiesDefinedData::instance + .COMPUTER_MANAGED[(short)this->units[DAT_CurrentUnitSlotID::instance].unitType] != 0) { DAT_GameState::instance.playerDataArray[_buildingID].currentPopulation_2 = DAT_GameState::instance.playerDataArray[_buildingID].currentPopulation_2 + 1; } DAT_UnitHasBecomeIdle::instance = 0; - if (this->units[uVar9].dying != 0 - && this->units[uVar9].state.generic != OpenSHC::Map::Units::States::US_DISAPPEAR) { - UVar6 = this->units[uVar9].unitType; + if (this->units[DAT_CurrentUnitSlotID::instance].dying != 0 + && this->units[DAT_CurrentUnitSlotID::instance].state.generic + != OpenSHC::Map::Units::States::US_DISAPPEAR) { + UVar6 = this->units[DAT_CurrentUnitSlotID::instance].unitType; if (UVar6 != OpenSHC::Map::Units::UT_BURNINGMAN && UVar6 != OpenSHC::Map::Units::UT_BURNING_ANIMAL_BIG && UVar6 != OpenSHC::Map::Units::UT_BURNING_ANIMAL_SMALL - && ((short)this->units[uVar9].state.generic < 0x6f - || 0x75 < (short)this->units[uVar9].state.generic)) { - this->units[uVar9].state.generic = OpenSHC::Map::Units::States::US_DEATH_01; + && ((short)this->units[DAT_CurrentUnitSlotID::instance].state.generic < 0x6f + || 0x75 < (short)this->units[DAT_CurrentUnitSlotID::instance].state.generic)) { + this->units[DAT_CurrentUnitSlotID::instance].state.generic + = OpenSHC::Map::Units::States::US_DEATH_01; this->units[DAT_CurrentUnitSlotID::instance].animationCycleNumber = 0; - uVar9 = DAT_CurrentUnitSlotID::instance; } } if (DAT_UnitPropertiesDefinedData::instance - .COMPUTER_CONTROLLED[(short)this->units[uVar9].unitType] + .COMPUTER_CONTROLLED[(short)this->units[DAT_CurrentUnitSlotID::instance].unitType] != 0) { - _buildingID = this->units[uVar9].workplaceBuildingID_1; + _buildingID = this->units[DAT_CurrentUnitSlotID::instance].workplaceBuildingID_1; if (DAT_BuildingsState::instance.buildings[_buildingID].uid - == this->units[uVar9].workplaceBuildingUID) { + == this->units[DAT_CurrentUnitSlotID::instance].workplaceBuildingUID) { if (DAT_BuildingsState::instance.buildings[_buildingID].sleeping != false) { MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func:: makeUnitStopWalkingByClearingPathProgressState, - this)(uVar9); + this)(DAT_CurrentUnitSlotID::instance); if (7 < this->units[DAT_CurrentUnitSlotID::instance].movementRelated) { this->units[DAT_CurrentUnitSlotID::instance].logicalState = OpenSHC::Map::Units::ULS_TRANSITIONING; @@ -612,13 +609,11 @@ namespace Map { this)(DAT_CurrentUnitSlotID::instance); } this->units[DAT_CurrentUnitSlotID::instance].disappearFadeAlphaCountdown = 0; - uVar9 = DAT_CurrentUnitSlotID::instance; } } else { MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func:: makeUnitStopWalkingByClearingPathProgressState, - this)(uVar9); - uVar9 = DAT_CurrentUnitSlotID::instance; + this)(DAT_CurrentUnitSlotID::instance); if (7 < this->units[DAT_CurrentUnitSlotID::instance].movementRelated) { this->units[DAT_CurrentUnitSlotID::instance].logicalState = OpenSHC::Map::Units::ULS_TRANSITIONING; @@ -629,11 +624,10 @@ namespace Map { MACRO_CALL_MEMBER( OpenSHC::Map::Units::UnitsState_Func::clearHiddenFlagAndUpdatePosition, this)( DAT_CurrentUnitSlotID::instance); - uVar9 = DAT_CurrentUnitSlotID::instance; } } } - this->units[uVar9].field131_0x2ac = 0; + this->units[DAT_CurrentUnitSlotID::instance].field131_0x2ac = 0; MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::processMeleeInitiation, this)( DAT_CurrentUnitSlotID::instance); this->units[DAT_CurrentUnitSlotID::instance].field143_0x2c4 @@ -647,7 +641,6 @@ namespace Map { (*DAT_UnitPropertiesDefinedData::instance.UpdateUnitFunctions [(short)this->units[DAT_CurrentUnitSlotID::instance].unitType])(); } - uVar9 = DAT_CurrentUnitSlotID::instance; UnitStateShort UVar8 = this->units[DAT_CurrentUnitSlotID::instance].field143_0x2c4; if (UVar8 != this->units[DAT_CurrentUnitSlotID::instance].state.generic && (UVar8 @@ -660,25 +653,25 @@ namespace Map { DAT_TileMapState::instance.moats[_troopValue].someCountDown = DAT_TileMapState::instance.moats[_troopValue].someCountDown + -0x14; } - this->units[uVar9].field41_0x5c = 0; + this->units[DAT_CurrentUnitSlotID::instance].field41_0x5c = 0; if (this->units[DAT_CurrentUnitSlotID::instance].usingTeleport == 0) { - piVar1 = &this->units[DAT_CurrentUnitSlotID::instance].field200_0x354; + _intFieldPtr = &this->units[DAT_CurrentUnitSlotID::instance].field200_0x354; /* Not climbing */ - *piVar1 = *piVar1 + 1; + *_intFieldPtr = *_intFieldPtr + 1; _troopValue = this->units[DAT_CurrentUnitSlotID::instance].field200_0x354; if ((int)this->units[DAT_CurrentUnitSlotID::instance].calculatedMovementSpeed + (int)this->units[DAT_CurrentUnitSlotID::instance].stateBasedSpeed + (int)this->units[DAT_CurrentUnitSlotID::instance].moveDelay < _troopValue - this->units[DAT_CurrentUnitSlotID::instance].field199_0x350) { this->units[DAT_CurrentUnitSlotID::instance].field199_0x350 = _troopValue; - psVar4 = &this->units[DAT_CurrentUnitSlotID::instance].movementRunUpTime; + _shortFieldPtr = &this->units[DAT_CurrentUnitSlotID::instance].movementRunUpTime; if (this->units[DAT_CurrentUnitSlotID::instance].movementRunUpTime <= 0) { - *psVar4 = 0; + *_shortFieldPtr = 0; } else { - *psVar4 = *psVar4 + -1; + *_shortFieldPtr = *_shortFieldPtr + -1; } _troopValue = MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::processUnitMove, this)(DAT_CurrentUnitSlotID::instance, @@ -859,25 +852,26 @@ namespace Map { = this->units[DAT_CurrentUnitSlotID::instance].imageIDUnk + this->units[DAT_CurrentUnitSlotID::instance].field218_0x37e * 8; break; - case 0x16: - uVar9 = ((int)this->units[DAT_CurrentUnitSlotID::instance] - .facingDirectionMapOrientationCorrected - + 4) + case 0x16: { + uint _correctedDirection = ((int)this->units[DAT_CurrentUnitSlotID::instance] + .facingDirectionMapOrientationCorrected + + 4) % 8; - this->units[DAT_CurrentUnitSlotID::instance].gfxNumber = uVar9 + 0x151; + this->units[DAT_CurrentUnitSlotID::instance].gfxNumber = _correctedDirection + 0x151; this->units[DAT_CurrentUnitSlotID::instance].gfxNumber = this->units[DAT_CurrentUnitSlotID::instance].gfxNumber + ((byte)this->units[DAT_CurrentUnitSlotID::instance].field218_0x37e & 3) * 8; - uVar9 = ((int)this->units[DAT_CurrentUnitSlotID::instance] - .facingDirectionMapOrientationCorrected - + 4) + _correctedDirection = ((int)this->units[DAT_CurrentUnitSlotID::instance] + .facingDirectionMapOrientationCorrected + + 4) % 8; - _troopValue = uVar9 + 0x1d1; + _troopValue = _correctedDirection + 0x1d1; this->units[DAT_CurrentUnitSlotID::instance].imageIDUnk = _troopValue; this->units[DAT_CurrentUnitSlotID::instance].imageIDUnk = this->units[DAT_CurrentUnitSlotID::instance].imageIDUnk + this->units[DAT_CurrentUnitSlotID::instance].field218_0x37e * 8; break; + } case 0x18: this->units[DAT_CurrentUnitSlotID::instance].gfxNumber = (int)this->units[DAT_CurrentUnitSlotID::instance] @@ -896,31 +890,31 @@ namespace Map { = this->units[DAT_CurrentUnitSlotID::instance].imageID2 + ((int)this->units[DAT_CurrentUnitSlotID::instance].field215_0x378 / 2) * 8; } - psVar4 = &this->units[DAT_CurrentUnitSlotID::instance].unitSpeedMatchingRelatedUnk; + _shortFieldPtr = &this->units[DAT_CurrentUnitSlotID::instance].unitSpeedMatchingRelatedUnk; if (this->units[DAT_CurrentUnitSlotID::instance].unitSpeedMatchingRelatedUnk != 0) { - *psVar4 = *psVar4 + -1; + *_shortFieldPtr = *_shortFieldPtr + -1; } - bVar13 = this->units[DAT_CurrentUnitSlotID::instance].fadeType; - if (bVar13 != 0) { - if (bVar13 == 1) { + byte _fadeAlpha = this->units[DAT_CurrentUnitSlotID::instance].fadeType; + if (_fadeAlpha != 0) { + if (_fadeAlpha == 1) { this->units[DAT_CurrentUnitSlotID::instance].disappearFadeAlphaCountdown = (byte)DAT_UnitPropertiesDefinedData::instance.FadeAlpha_Values_1_2 [(char)this->units[DAT_CurrentUnitSlotID::instance].fadeCounter]; } else { - if (bVar13 == 2) { - bVar13 = (byte)DAT_UnitPropertiesDefinedData::instance.FadeAlpha_Values_1_2 - [(char)this->units[DAT_CurrentUnitSlotID::instance].fadeCounter]; + if (_fadeAlpha == 2) { + _fadeAlpha = (byte)DAT_UnitPropertiesDefinedData::instance.FadeAlpha_Values_1_2 + [(char)this->units[DAT_CurrentUnitSlotID::instance].fadeCounter]; } else { - byte bVar5 = this->units[DAT_CurrentUnitSlotID::instance].fadeCounter; - if (bVar13 == 3) { - bVar13 = (byte)DAT_UnitPropertiesDefinedData::instance - .FadeAlpha_Values_3[(char)bVar5]; + byte _fadeCounter = this->units[DAT_CurrentUnitSlotID::instance].fadeCounter; + if (_fadeAlpha == 3) { + _fadeAlpha = (byte)DAT_UnitPropertiesDefinedData::instance + .FadeAlpha_Values_3[(char)_fadeCounter]; } else { - bVar13 = (byte)DAT_UnitPropertiesDefinedData::instance - .FadeAlpha_Values_4[(char)bVar5]; + _fadeAlpha = (byte)DAT_UnitPropertiesDefinedData::instance + .FadeAlpha_Values_4[(char)_fadeCounter]; } } - this->units[DAT_CurrentUnitSlotID::instance].disappearFadeAlphaCountdown = bVar13; + this->units[DAT_CurrentUnitSlotID::instance].disappearFadeAlphaCountdown = _fadeAlpha; } this->units[DAT_CurrentUnitSlotID::instance].fadeCounter = this->units[DAT_CurrentUnitSlotID::instance].fadeCounter + 1; From 3de206bda3647339be4536191e62413bf16337eb Mon Sep 17 00:00:00 2001 From: Gynt Date: Mon, 28 Sep 2026 22:17:24 +0200 Subject: [PATCH 289/299] reimplement: updateUnits 40.9% -> 41.2%, unpick two comma-operator conditions The decompiler writes a field read inside a condition as an assignment joined by a comma operator, reusing one register for unrelated fields while it does: _buildingID held both a unit type and a state inside the same condition. Nesting the tests gives each field its own name and keeps the short-circuit order. Measured tied at 41.10%, so kept for readability. The loop head now uses the loop''s own index instead of re-reading DAT_CurrentUnitSlotID::instance, worth 0.2%. This refines the previous commit rather than contradicting it: the choice is per-region, not global. After a call the original reloads the global, so read it directly there; in a call-free stretch like the loop head it keeps a scaled index in a register (imul eax, eax, 0x490) and reuses it, so use the local. No call runs between _currentUnitID being assigned and the end of that stretch. Two hypotheses from reading the diff measured worse and were dropped: swapping the arms of the lord/disappear if (40.8%), and an apparent field mix-up that turned out not to exist. The diff showed us writing destinationNeeded where the original writes updateTickTracker, but counting the writes on each side gives three and one on both, so difflib had simply paired two unrelated adjacent instructions that differ by three characters. A substitution pair in the alignment is not evidence that two instructions correspond; count occurrences per side before believing one. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01A4PvfebpUzaMXy93EutBjJ --- .../Map/Units/UnitsState/updateUnits.cpp | 55 ++++++++++--------- 1 file changed, 29 insertions(+), 26 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/updateUnits.cpp b/src/OpenSHC/Map/Units/UnitsState/updateUnits.cpp index cd9aa5743..e1ae2fb87 100644 --- a/src/OpenSHC/Map/Units/UnitsState/updateUnits.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/updateUnits.cpp @@ -78,23 +78,23 @@ namespace Map { DAT_CurrentUnitSlotID::instance = 1; do { _currentUnitID = DAT_CurrentUnitSlotID::instance; - if (this->units[DAT_CurrentUnitSlotID::instance].logicalState != OpenSHC::Map::Units::ULS_INVISIBLE) { - this->maxUnitCount = DAT_CurrentUnitSlotID::instance + 1; - this->units[DAT_CurrentUnitSlotID::instance].field233_0x39a = 0; - this->units[DAT_CurrentUnitSlotID::instance].attackedBy = 0; - this->units[DAT_CurrentUnitSlotID::instance].huntedBy = 0; - this->units[DAT_CurrentUnitSlotID::instance].field265_0x3dc = 0; - this->units[DAT_CurrentUnitSlotID::instance].field43_0x64 = 0; + if (this->units[_currentUnitID].logicalState != OpenSHC::Map::Units::ULS_INVISIBLE) { + this->maxUnitCount = _currentUnitID + 1; + this->units[_currentUnitID].field233_0x39a = 0; + this->units[_currentUnitID].attackedBy = 0; + this->units[_currentUnitID].huntedBy = 0; + this->units[_currentUnitID].field265_0x3dc = 0; + this->units[_currentUnitID].field43_0x64 = 0; /* This literally does nothing, this variable is not used elsewhere, what the hell? */ - _shortFieldPtr = &this->units[DAT_CurrentUnitSlotID::instance].targetShootRelated; - if (this->units[DAT_CurrentUnitSlotID::instance].targetShootRelated != 0) { + _shortFieldPtr = &this->units[_currentUnitID].targetShootRelated; + if (this->units[_currentUnitID].targetShootRelated != 0) { *_shortFieldPtr = *_shortFieldPtr + -1; } - if ((this->units[DAT_CurrentUnitSlotID::instance].state.generic + if ((this->units[_currentUnitID].state.generic == OpenSHC::Map::Units::States::US_DETERMINE_NEXT_STATEUnk) && (_troopValue = MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::isUnitRegisteredOnItsOwnTile, @@ -432,17 +432,19 @@ namespace Map { } } } - _buildingID = this->units[DAT_CurrentUnitSlotID::instance].unitType; - if (((_buildingID == OpenSHC::Map::Units::UT_E_ARCHER) - || (_buildingID == OpenSHC::Map::Units::UT_A_ARCHER)) - && (_buildingID = this->units[DAT_CurrentUnitSlotID::instance].state.generic, - _buildingID == OpenSHC::Map::Units::States::US_AIM_WEAPONUnk - || (_buildingID == OpenSHC::Map::Units::States::US_FIRE_WEAPONUnk)) - && (_troopValue = this->units[DAT_CurrentUnitSlotID::instance].shootTargetedUnit, - 0 < _troopValue - && (this->units[_troopValue].uid - == this->units[DAT_CurrentUnitSlotID::instance].targetUID))) { - this->units[_troopValue].field233_0x39a = 1; + if ((this->units[DAT_CurrentUnitSlotID::instance].unitType == OpenSHC::Map::Units::UT_E_ARCHER + || this->units[DAT_CurrentUnitSlotID::instance].unitType + == OpenSHC::Map::Units::UT_A_ARCHER) + && (this->units[DAT_CurrentUnitSlotID::instance].state.generic + == OpenSHC::Map::Units::States::US_AIM_WEAPONUnk + || this->units[DAT_CurrentUnitSlotID::instance].state.generic + == OpenSHC::Map::Units::States::US_FIRE_WEAPONUnk)) { + _troopValue = this->units[DAT_CurrentUnitSlotID::instance].shootTargetedUnit; + if (0 < _troopValue + && this->units[_troopValue].uid + == this->units[DAT_CurrentUnitSlotID::instance].targetUID) { + this->units[_troopValue].field233_0x39a = 1; + } } if (this->units[DAT_CurrentUnitSlotID::instance].enemyNoticeFrequencyUnk != 0 && (DAT_GameState::instance.mapAndTime.totalGameTicksUnk @@ -647,11 +649,12 @@ namespace Map { == (OpenSHC::Map::Units::States::US_DEATH_02 | OpenSHC::Map::Units::States::US_STAND_UPUnk | OpenSHC::Map::Units::States::US_RELOAD_WEAPONUnk) - || (UVar8 == OpenSHC::Map::Units::States::US_DIG)) - && (_troopValue = this->units[DAT_CurrentUnitSlotID::instance].digTileTarget, - DAT_TileMapState::instance.moats[_troopValue].owner != '\0')) { - DAT_TileMapState::instance.moats[_troopValue].someCountDown - = DAT_TileMapState::instance.moats[_troopValue].someCountDown + -0x14; + || (UVar8 == OpenSHC::Map::Units::States::US_DIG))) { + _troopValue = this->units[DAT_CurrentUnitSlotID::instance].digTileTarget; + if (DAT_TileMapState::instance.moats[_troopValue].owner != '\0') { + DAT_TileMapState::instance.moats[_troopValue].someCountDown + = DAT_TileMapState::instance.moats[_troopValue].someCountDown + -0x14; + } } this->units[DAT_CurrentUnitSlotID::instance].field41_0x5c = 0; if (this->units[DAT_CurrentUnitSlotID::instance].usingTeleport == 0) { From 0ea2c2bf1e8f3c7d5fc87181885730ff3eaec938 Mon Sep 17 00:00:00 2001 From: Gynt Date: Mon, 28 Sep 2026 22:58:36 +0200 Subject: [PATCH 290/299] fix: try_styles.py compared rounded percentages, hiding small regressions measure() parsed the percentage out of reccmp_report.py''s printed output, which is formatted to one decimal. Every variant sharing a first decimal therefore compared as exactly equal, and the tie check confirmed the tie. It now reads the ratio from diff.json and prints four decimals. This was not hypothetical. A processMeleeInitiation variant that rewrote the occupancy-row byte arithmetic as directionTranslationMatrix indexing printed the same "29.20%" as the baseline and was kept for readability; it was really 29.1840% against 29.2042%, one instruction worse. Reverted. Large results are unaffected, because those were verified with "reccmp_report.py cmp" against a snapshot, which compares the floats. The one change that survived measurement here is uint -> int for _neighbourHeights, an exact tie at 29.2042% and the more honest type: those values are only ever used in signed subtraction. processMeleeInitiation does not move on source shape. Nine hypotheses now: caching the flags global (24.2%), looping the eight unrolled height calls (21.6%), both (16.5%) and hoisting a shared row pointer (21.4%) are all much worse; array declaration order and the element type are exact ties. The diff shows the original holding zero in bx to compare against, addressing locals through ebp at a negative offset, and running a 4-byte smaller frame -- all register allocation and frame layout, which the source does not reach. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01A4PvfebpUzaMXy93EutBjJ --- src/OpenSHC/Map/Units/UnitsState/processMeleeInitiation.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/processMeleeInitiation.cpp b/src/OpenSHC/Map/Units/UnitsState/processMeleeInitiation.cpp index c05c7c847..8fd32b608 100644 --- a/src/OpenSHC/Map/Units/UnitsState/processMeleeInitiation.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/processMeleeInitiation.cpp @@ -27,7 +27,7 @@ namespace Map { void UnitsState::processMeleeInitiation(int unitID) { - uint _neighbourHeights[8]; + int _neighbourHeights[8]; int _totalHeight; uint* _occupancyRow; int _adjacentTiles[24]; From df10692e16d13fd2efbf64a7045db2e6dd4272de Mon Sep 17 00:00:00 2001 From: Gynt Date: Tue, 29 Sep 2026 00:17:36 +0200 Subject: [PATCH 291/299] reimplement: calculateUnitMovementSpeed 26.4% -> 31.1%, one signed read per field diff_types.py reports movsx on the original against movzx on ours for OrganismLayer and for units[].owner. Both are declared short and UnitTypeShort is a typedef short, so the generated headers are right -- the fault is at the use site. Reading the same field several times in mixed contexts makes MSVC emit movzx plus a separate "movsx r, r16"; the original loads it once, signed. One int local per field gives that single movsx: organism_local 25.55% -> 25.88% OrganismLayer, read three times owner_local 25.55% -> 28.63% units[].owner, read three times both 25.55% -> 30.26% more than additive Confirmed at 26.4% -> 31.1% with the struct resolvers enabled, and diff_types.py now reports no type hints for this function. This settles an ambiguity in AGENTS.md, which says to access fields repeatedly rather than copy them into locals, and separately that naming a repeatedly read field is unpredictable and must be measured. Both hold; the EXTEND hint is the missing discriminator. When the diff shows movzx plus movsx against a single movsx, the local is the original''s own reading rather than a gamble. processEntityDamageToUnit also stops reusing one local for both a shooter id and a tile -- the decompiler could reuse that register because the cow-poison branch returns before the id is needed again. An exact tie at 36.4%. Declaring its three int flags as bool, which is what the decompiler shows, measured 0.43% worse and was dropped. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01A4PvfebpUzaMXy93EutBjJ --- .../Units/UnitsState/calculateUnitMovementSpeed.cpp | 13 +++++++------ .../Units/UnitsState/processEntityDamageToUnit.cpp | 9 ++++----- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/calculateUnitMovementSpeed.cpp b/src/OpenSHC/Map/Units/UnitsState/calculateUnitMovementSpeed.cpp index 2e9991a98..b856c5b85 100644 --- a/src/OpenSHC/Map/Units/UnitsState/calculateUnitMovementSpeed.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/calculateUnitMovementSpeed.cpp @@ -36,9 +36,9 @@ namespace Map { this->units[unitID].isMatchingSpeed = false; uint _isInMoat = _logicFlags & 0x20000000; byte _tileHeight = DAT_TileMapState::instance.HeightLayer[_tile]; - if (DAT_TileMapState::instance.OrganismLayer[_tile] != 0 - && DAT_TileMapState::instance.OrganismLayer[_tile] < 2000) { - DAT_LandscapeState::instance.trees[DAT_TileMapState::instance.OrganismLayer[_tile]].state = 3; + int _organismID = DAT_TileMapState::instance.OrganismLayer[_tile]; + if (_organismID != 0 && _organismID < 2000) { + DAT_LandscapeState::instance.trees[_organismID].state = 3; } if (_isInMoat != 0 && (DAT_TileMapState::instance.MacroLayer[_tile] & 0x3f) == 1) { _isInMoat = 0; @@ -158,7 +158,8 @@ namespace Map { return; } this->units[unitID].field289_0x3ff = 1; - if (DAT_BuildingsState::instance.buildings[_buildingID].owner == this->units[unitID].owner) { + int _owner = this->units[unitID].owner; + if (DAT_BuildingsState::instance.buildings[_buildingID].owner == _owner) { return; } if (this->units[unitID].dying != 0) { @@ -167,10 +168,10 @@ namespace Map { if (this->units[unitID].logicalState != OpenSHC::Map::Units::ULS_NORMAL) { return; } - if (this->units[unitID].owner == 0) { + if (_owner == 0) { return; } - if (DAT_GameSynchronyState::instance.currentPlayerFullIDArray[this->units[unitID].owner] != -1) { + if (DAT_GameSynchronyState::instance.currentPlayerFullIDArray[_owner] != -1) { return; } DAT_TroopValueState::instance.attackInfo.field128058_0x469dc diff --git a/src/OpenSHC/Map/Units/UnitsState/processEntityDamageToUnit.cpp b/src/OpenSHC/Map/Units/UnitsState/processEntityDamageToUnit.cpp index df814394a..d5f859b56 100644 --- a/src/OpenSHC/Map/Units/UnitsState/processEntityDamageToUnit.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/processEntityDamageToUnit.cpp @@ -75,12 +75,12 @@ namespace Map { if (this->units[unitID].dying != 0) { return FALSE; } - _entityShootingUnitID_2 = DAT_UnitsState::instance.units[unitID].tile; + int _unitTile = DAT_UnitsState::instance.units[unitID].tile; /* if the tile that the unit is on has some properties, don't bother either. */ - if ((DAT_TileMapState::instance.LogicLayer[_entityShootingUnitID_2] & 0x10000100U) != 0) { + if ((DAT_TileMapState::instance.LogicLayer[_unitTile] & 0x10000100U) != 0) { return FALSE; } /* @@ -88,9 +88,8 @@ namespace Map { building, return 0 */ - if (DAT_TileMapState::instance.BuildingLayer[_entityShootingUnitID_2] != 0) { - switch (DAT_BuildingsState::instance - .buildings[DAT_TileMapState::instance.BuildingLayer[_entityShootingUnitID_2]] + if (DAT_TileMapState::instance.BuildingLayer[_unitTile] != 0) { + switch (DAT_BuildingsState::instance.buildings[DAT_TileMapState::instance.BuildingLayer[_unitTile]] .buildingType) { case OpenSHC::Map::Buildings::BT_MANORHOUSE: case OpenSHC::Map::Buildings::BT_STONEKEEP: From 96cbe8b32891ce9527ed19f18a32ab20fd1a8132 Mon Sep 17 00:00:00 2001 From: Gynt Date: Tue, 29 Sep 2026 01:02:49 +0200 Subject: [PATCH 292/299] reimplement: resetUnitMovementState 100% Reimplemented, one int local diff_types.py flagged movsx on the original against movzx on ours for units[].unknownTestAgainst0_2. The field is already short and so is the local that reads it, which makes the load 16-bit; the original sign-extends into a 32-bit register, which is what an int local does. Widening that one local takes the function from 85.7% to 95.2%, and normalized to 100% -- only call targets differ now. Widening an existing local is not the same operation as introducing one, and the difference decides whether this family of fixes helps: * introducing a local changes how many times memory is read, and MSVC often prefers to compare against the memory operand instead. Doing that to a field feeding an == constant chain cost 11.8% in playHurtSFXForUnit. * widening a local only changes the extension width of a read that already happens once, so it cannot add a load. setMoveDelayForUnitsOnSameTiles has the same defect at array scope: its scratch array is ushort and all fifteen reads cast back with (short). The original reads the element signed in one movsx. Declaring the array short says that without the casts and measured an exact tie at 19.3211%, so it is kept for the fifteen casts it removes rather than for the match. Also completes the earlier try_styles.py fix. Restoring the build list was not enough: the trials leave the DLL built from the narrowed list, so diff.json kept reporting one function at the last variant''s score and reccmp_report.py --run could not repair it. It now rebuilds with the full list before exiting, which costs a few minutes per invocation and is worth it. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01A4PvfebpUzaMXy93EutBjJ --- .../UnitsState/resetUnitMovementState.cpp | 2 +- .../setMoveDelayForUnitsOnSameTiles.cpp | 40 +++++++++---------- .../batch/try_styles.py | 6 +++ 3 files changed, 27 insertions(+), 21 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/resetUnitMovementState.cpp b/src/OpenSHC/Map/Units/UnitsState/resetUnitMovementState.cpp index 70a9bbfa4..7755e5d6c 100644 --- a/src/OpenSHC/Map/Units/UnitsState/resetUnitMovementState.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/resetUnitMovementState.cpp @@ -7,7 +7,7 @@ namespace Map { // FUNCTION: STRONGHOLDCRUSADER 0x0053E870 void UnitsState::resetUnitMovementState(int unitID) { - short _wasPositionPending = this->units[unitID].unknownTestAgainst0_2; + int _wasPositionPending = this->units[unitID].unknownTestAgainst0_2; this->units[unitID].currentIndexInPathPlan = 0; this->units[unitID].tunnelerFinishedDigging = 0; this->units[unitID].movementRelated = 8; diff --git a/src/OpenSHC/Map/Units/UnitsState/setMoveDelayForUnitsOnSameTiles.cpp b/src/OpenSHC/Map/Units/UnitsState/setMoveDelayForUnitsOnSameTiles.cpp index 3b0457478..b30f90320 100644 --- a/src/OpenSHC/Map/Units/UnitsState/setMoveDelayForUnitsOnSameTiles.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/setMoveDelayForUnitsOnSameTiles.cpp @@ -10,7 +10,7 @@ namespace Map { // FUNCTION: STRONGHOLDCRUSADER 0x0052F260 void UnitsState::setMoveDelayForUnitsOnSameTiles(int unitID, int unitIDCurrentTilePosition) { - ushort _unitIDArray[2010]; + short _unitIDArray[2010]; int _lowestMovementSpeed = 0x14; this->units[unitID].unitOrderWhenOnSameTile = 0; if (this->units[unitID].unknownTestAgainst0_2 != 0) { @@ -31,11 +31,11 @@ namespace Map { while (true) { _writeIndex = _index; if (unitID < _unitIDOfAUnitOnSameTile && !_isInserted) { - _unitIDArray[_index] = (ushort)unitID; + _unitIDArray[_index] = (short)unitID; _writeIndex = _index + 1; _isInserted = true; } - _unitIDArray[_writeIndex] = (ushort)_unitIDOfAUnitOnSameTile; + _unitIDArray[_writeIndex] = (short)_unitIDOfAUnitOnSameTile; _unitIDOfAUnitOnSameTile = (short)this->units[_unitIDOfAUnitOnSameTile].nextUnitOnTheSameTile; if (_unitIDOfAUnitOnSameTile < 1) { break; @@ -48,39 +48,39 @@ namespace Map { } _writeIndex = _writeIndex + 1; if (!_isInserted) { - _unitIDArray[_writeIndex] = (ushort)unitID; + _unitIDArray[_writeIndex] = (short)unitID; _writeIndex = _writeIndex + 2; } _unitIDArray[_writeIndex] = 0; - DAT_TileMapState::instance.UnitLayer[unitIDCurrentTilePosition] = _unitIDArray[0]; - this->units[(short)_unitIDArray[0]].unitOrderWhenOnSameTile = 0; - int _previousUnitID = (short)_unitIDArray[0]; + DAT_TileMapState::instance.UnitLayer[unitIDCurrentTilePosition] = (ushort)_unitIDArray[0]; + this->units[_unitIDArray[0]].unitOrderWhenOnSameTile = 0; + int _previousUnitID = _unitIDArray[0]; for (int _order = 1; _order < 2001; ++_order) { this->units[_previousUnitID].nextUnitOnTheSameTile = _unitIDArray[_order]; - if ((short)_unitIDArray[_order] < 1) { + if (_unitIDArray[_order] < 1) { break; } - this->units[(short)_unitIDArray[_order]].unitOrderWhenOnSameTile = (short)_order; - _previousUnitID = (short)_unitIDArray[_order]; + this->units[_unitIDArray[_order]].unitOrderWhenOnSameTile = (short)_order; + _previousUnitID = _unitIDArray[_order]; } for (int i = 0; i < 2000; ++i) { - if ((short)_unitIDArray[i] < 1) { + if (_unitIDArray[i] < 1) { break; } - if (this->units[(short)_unitIDArray[i]].tunnelerFinishedDigging == 2 - && this->units[(short)_unitIDArray[i]].movementSpeed < _lowestMovementSpeed) { - _lowestMovementSpeed = this->units[(short)_unitIDArray[i]].movementSpeed; + if (this->units[_unitIDArray[i]].tunnelerFinishedDigging == 2 + && this->units[_unitIDArray[i]].movementSpeed < _lowestMovementSpeed) { + _lowestMovementSpeed = this->units[_unitIDArray[i]].movementSpeed; } } for (int i = 0; i < 2000; ++i) { - if ((short)_unitIDArray[i] < 1) { + if (_unitIDArray[i] < 1) { break; } - if (this->units[(short)_unitIDArray[i]].tunnelerFinishedDigging == 2 - && this->units[(short)_unitIDArray[i]].moveDelay == 0) { - if (_lowestMovementSpeed < this->units[(short)_unitIDArray[i]].movementSpeed) { - this->units[(short)_unitIDArray[i]].moveDelay - = this->units[(short)_unitIDArray[i]].unitOrderWhenOnSameTile / 2 + 1; + if (this->units[_unitIDArray[i]].tunnelerFinishedDigging == 2 + && this->units[_unitIDArray[i]].moveDelay == 0) { + if (_lowestMovementSpeed < this->units[_unitIDArray[i]].movementSpeed) { + this->units[_unitIDArray[i]].moveDelay + = this->units[_unitIDArray[i]].unitOrderWhenOnSameTile / 2 + 1; } else { _lowestMovementSpeed = 0; } diff --git a/tools/reimplementation-helper/batch/try_styles.py b/tools/reimplementation-helper/batch/try_styles.py index 5c5036458..5bc2d5a82 100644 --- a/tools/reimplementation-helper/batch/try_styles.py +++ b/tools/reimplementation-helper/batch/try_styles.py @@ -107,6 +107,12 @@ def main(): (vdir / "results.json").write_text( json.dumps({s: p for p, s in results if p is not None}, indent=1), encoding="utf-8") + # The trials left the DLL and reccmp/dll/diff.json built from the narrowed list, so every + # batch tool would go on reporting the last variant's single-function result. Restoring + # the list is not enough -- rebuild so the tree, the DLL and the diff agree again. + print("\nrebuilding with the full list so later reports are valid...") + print(run(BATCH / "build_quiet.py").strip().splitlines()[-1]) + if __name__ == "__main__": main() From eb556dccd17aa60594e6dcd576e7b2aa45599e9b Mon Sep 17 00:00:00 2001 From: Gynt Date: Tue, 29 Sep 2026 01:29:33 +0200 Subject: [PATCH 293/299] reimplement: widen short locals holding a field read, 5 functions Same fix as resetUnitMovementState, applied to every short/ushort local that holds a 16-bit field read in the functions diff_types.py flags. The local is declared after the field, so the load is 16-bit and needs a second instruction to sign-extend; the original sign-extends in one movsx, which is what an int local does. setUnitFacingDirectionForTargetXandY 86.1% -> 90.4% acquireShootTarget 41.0% -> 43.3% setUnitFacingDirectionBasedOnBuilding 71.4% -> 73.5% processEntityDamageToUnit 36.4% -> 38.0% processUnitMove 61.4% -> 62.5% updateUnits'' _aiBehaviour was widened too and measured 0.3% worse, so it stays short. That fits the boundary this family of fixes obeys, now confirmed three times independently: helps the value feeds arithmetic, indexing, or a comparison against another variable hurts the value feeds comparisons against constants, which MSVC compiles against the memory operand directly _aiBehaviour feeds a switch and an == 10 test; playHurtSFXForUnit''s unitType feeds a twelve-way == chain and cost 11.8% when given a local at all. _pathIndex went from ushort to int, which zero-extends either way, so there was no movsx to gain there -- processUnitMove''s gain came from its _destinationX and _destinationY siblings. Signedness is what matters, not width. All 18 candidates were changed in one batch and measured in a single build, since each is confined to one function and reccmp reports per function; the one loser was then reverted on its own. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01A4PvfebpUzaMXy93EutBjJ --- .../Map/Units/UnitsState/acquireShootTarget.cpp | 14 +++++++------- .../Units/UnitsState/processEntityDamageToUnit.cpp | 10 +++++----- .../Map/Units/UnitsState/processUnitMove.cpp | 6 +++--- .../setUnitFacingDirectionBasedOnBuilding.cpp | 2 +- .../setUnitFacingDirectionForTargetXandY.cpp | 2 +- 5 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/acquireShootTarget.cpp b/src/OpenSHC/Map/Units/UnitsState/acquireShootTarget.cpp index 71d019443..85f1e1d83 100644 --- a/src/OpenSHC/Map/Units/UnitsState/acquireShootTarget.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/acquireShootTarget.cpp @@ -93,7 +93,7 @@ namespace Map { fetch the targetedUnitID */ - short _mannedEngineTargetID = this->units[unitID].targetedUnitID__OR__engineerMannedSiegeEngineRef; + int _mannedEngineTargetID = this->units[unitID].targetedUnitID__OR__engineerMannedSiegeEngineRef; int _0x04_targetUnitID = (int)_mannedEngineTargetID; if (this->units[_0x04_targetUnitID].uid == this->units[unitID] @@ -164,7 +164,7 @@ namespace Map { } } } - short _savedDestinationX = this->units[unitID]._someX_2; + int _savedDestinationX = this->units[unitID]._someX_2; this->units[unitID].targetedUnitID__OR__engineerMannedSiegeEngineRef = 0; this->units[unitID].shootTargetedUnit = 0; this->units[unitID].targetingType = OpenSHC::Map::Units::UIT_NO_INSTRUCTION_OR_MOVEUnk; @@ -184,7 +184,7 @@ namespace Map { get the workplace building id */ - short _ditchID = this->units[unitID].targetID_OR_targetBuildingID; + int _ditchID = this->units[unitID].targetID_OR_targetBuildingID; int _brazierEntityID; if (DAT_TileMapState::instance.pitchDitches[_ditchID].uid == this->units[unitID] @@ -203,7 +203,7 @@ namespace Map { return TRUE; } } else if (this->units[unitID].targetingType == OpenSHC::Map::Units::UIT_ATTACK_BUILDING) { - short _buildingID = this->units[unitID].targetID_OR_targetBuildingID; + int _buildingID = this->units[unitID].targetID_OR_targetBuildingID; if (DAT_BuildingsState::instance.buildings[_buildingID].uid == this->units[unitID] .targetedUnitUIDUnk_OR_someAppearTileUnk_OR_buildingUID_OR_pitchDitchUID_OR_entityUID) { @@ -257,7 +257,7 @@ namespace Map { continue; break; case OpenSHC::Map::Units::UT_LIONSHWOLF: { - short _enemyTribeID = this->units[_enemy].tribeID; + int _enemyTribeID = this->units[_enemy].tribeID; if (DAT_TribesState::instance.tribes[_enemyTribeID].unknownBool02 != 0 || (DAT_TribesState::instance.tribes[_enemyTribeID].unknownBool01 == 0 && ((this->units[_enemy].state.generic != 0xcf @@ -521,8 +521,8 @@ namespace Map { this->units[_validTargetID].field233_0x39a = 1; return TRUE; } - short _attackTileY = this->units[unitID].attackAtTileY; - short _attackTileX = this->units[unitID].attackAtTileX; + int _attackTileY = this->units[unitID].attackAtTileY; + int _attackTileX = this->units[unitID].attackAtTileX; this->units[unitID].jugglerCount = -1; BOOLEnum _tileIsValid = MACRO_CALL_MEMBER(OpenSHC::Rendering::ViewportRenderState_Func::xyAreValid, DAT_ViewportRenderState::ptr)((int)_attackTileX, (uint)(_attackTileY)); diff --git a/src/OpenSHC/Map/Units/UnitsState/processEntityDamageToUnit.cpp b/src/OpenSHC/Map/Units/UnitsState/processEntityDamageToUnit.cpp index d5f859b56..010fa7923 100644 --- a/src/OpenSHC/Map/Units/UnitsState/processEntityDamageToUnit.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/processEntityDamageToUnit.cpp @@ -52,7 +52,7 @@ namespace Map { int _siegeProjectile = 0; int _usesFemaleDeathScream = 0; UnitTypeShort _unitType = this->units[unitID].unitType; - short _entityShootingUnitID = DAT_EntityState::instance.entityArray[entityID].unitID_OR_seaGullID; + int _entityShootingUnitID = DAT_EntityState::instance.entityArray[entityID].unitID_OR_seaGullID; int _entityShootingUnitID_2 = (int)_entityShootingUnitID; if (unitID <= 0) { return FALSE; @@ -178,8 +178,8 @@ namespace Map { || _entityType == OpenSHC::Map::Entities::ET_FIREBALLISTA) { _siegeProjectile = 1; } - short _unitPlayerID = this->units[unitID].owner; - short _entityPlayerID = DAT_EntityState::instance.entityArray[entityID].owner; + int _unitPlayerID = this->units[unitID].owner; + int _entityPlayerID = DAT_EntityState::instance.entityArray[entityID].owner; if (((DAT_GameState::instance.mapAndTime.playerTeams[_entityPlayerID] == DAT_GameState::instance.mapAndTime.playerTeams[_unitPlayerID]) && (( @@ -296,8 +296,8 @@ namespace Map { if (0 < _unknown) { DAT_TribesState::instance.tribes[_unknown].field133_0x278 = 1; } - short _unitYPosition = this->units[unitID].y; - short _unitXPosition = this->units[unitID].x; + int _unitYPosition = this->units[unitID].y; + int _unitXPosition = this->units[unitID].x; this->units[unitID].animationCycleNumber = 0; this->units[unitID].state.generic = OpenSHC::Map::Units::States::US_STONE_DEATH_01; this->units[unitID].tunnelerFinishedDigging = 1; diff --git a/src/OpenSHC/Map/Units/UnitsState/processUnitMove.cpp b/src/OpenSHC/Map/Units/UnitsState/processUnitMove.cpp index bee3499fd..e4e268b93 100644 --- a/src/OpenSHC/Map/Units/UnitsState/processUnitMove.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/processUnitMove.cpp @@ -97,7 +97,7 @@ namespace Map { this->units[unitID].field105_0xe8 = 1; } } else { - ushort _pathIndex = this->units[unitID].currentIndexInPathPlan; + int _pathIndex = this->units[unitID].currentIndexInPathPlan; if (this->units[unitID].totalSizeOfPathPlan <= (short)_pathIndex && this->units[unitID].field280_0x3f4 == 0) { this->units[unitID].unknownMovementRelated_0x2d2 = 0; @@ -142,8 +142,8 @@ namespace Map { } } this->unknownInitially0_01 = this->unknownInitially0_01 + 1; - short _destinationY = this->units[unitID].destinationYPosition; - short _destinationX = this->units[unitID].destinationXPosition; + int _destinationY = this->units[unitID].destinationYPosition; + int _destinationX = this->units[unitID].destinationXPosition; bool _destinationReachable = false; if (MACRO_CALL_MEMBER(OpenSHC::Rendering::ViewportRenderState_Func::xyAreValid, DAT_ViewportRenderState::ptr)(_destinationX, _destinationY) diff --git a/src/OpenSHC/Map/Units/UnitsState/setUnitFacingDirectionBasedOnBuilding.cpp b/src/OpenSHC/Map/Units/UnitsState/setUnitFacingDirectionBasedOnBuilding.cpp index 01a44ea62..7843d74af 100644 --- a/src/OpenSHC/Map/Units/UnitsState/setUnitFacingDirectionBasedOnBuilding.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/setUnitFacingDirectionBasedOnBuilding.cpp @@ -15,7 +15,7 @@ namespace Map { if (buildingID == 0) { return 0; } - short _previousFacingDirection = this->units[unitID].facingDirection; + int _previousFacingDirection = this->units[unitID].facingDirection; MACRO_CALL_MEMBER( OpenSHC::Map::Navigation::DirectionAlgorithmState_Func::calculatePreferredRelativeOrientation, DAT_DirectionAlgorithmState::ptr)(this->units[unitID].x, this->units[unitID].y, diff --git a/src/OpenSHC/Map/Units/UnitsState/setUnitFacingDirectionForTargetXandY.cpp b/src/OpenSHC/Map/Units/UnitsState/setUnitFacingDirectionForTargetXandY.cpp index 0c199f18d..dcb1ced76 100644 --- a/src/OpenSHC/Map/Units/UnitsState/setUnitFacingDirectionForTargetXandY.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/setUnitFacingDirectionForTargetXandY.cpp @@ -14,7 +14,7 @@ namespace Map { // FUNCTION: STRONGHOLDCRUSADER 0x0052FE90 BOOLEnum UnitsState::setUnitFacingDirectionForTargetXandY(int unitID, int targetX, int targetY) { - short _previousFacingDirection = this->units[unitID].facingDirection; + int _previousFacingDirection = this->units[unitID].facingDirection; MACRO_CALL_MEMBER( OpenSHC::Map::Navigation::DirectionAlgorithmState_Func::calculatePreferredRelativeOrientation, DAT_DirectionAlgorithmState::ptr)(this->units[unitID].x, this->units[unitID].y, targetX, targetY); From 2f9f163c23a49cba712acd3a2fb8cb586d3d68d1 Mon Sep 17 00:00:00 2001 From: Gynt Date: Tue, 29 Sep 2026 01:46:12 +0200 Subject: [PATCH 294/299] reimplement: widen byte-sized flag locals to int, 3 functions diff_triage.py''s BYTE column counts byte-sized [esp] accesses per side. Where it is nonzero only on ours, those locals are ints in the original. The direction was already evidenced from the other side: declaring three int flags as bool in processEntityDamageToUnit, which is what the decompiler shows, cost 0.43%. updateUnitFadeAndVisibilityNearStructures 39.4% -> 51.4% 16 byte accesses findNearestEnemyAndHeadTowardsIt 34.4% -> 37.2% 7 stopUnitIfNextToTarget 30.0% -> 30.8% 4 giveMoveCommand''s _canReachDestination was widened too and measured 3.0% worse, so it stays bool. It differs from the others in a way worth recording: the three that gained start from a constant and are assigned true or false, while this one is initialised from a BOOLEnum-returning call. `bool x = call()` emits a test that normalises the result to 0 or 1; `int x = call()` stores it raw, so there the bool conversion is part of the codegen rather than an artefact of it. So: widen a byte-sized local when it holds a flag set from constants, leave it when it is initialised from a call''s return value. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01A4PvfebpUzaMXy93EutBjJ --- .../findNearestEnemyAndHeadTowardsIt.cpp | 24 +++++++++---------- .../UnitsState/stopUnitIfNextToTarget.cpp | 6 ++--- ...ateUnitFadeAndVisibilityNearStructures.cpp | 10 ++++---- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/findNearestEnemyAndHeadTowardsIt.cpp b/src/OpenSHC/Map/Units/UnitsState/findNearestEnemyAndHeadTowardsIt.cpp index 62e8d576b..a7b9803cc 100644 --- a/src/OpenSHC/Map/Units/UnitsState/findNearestEnemyAndHeadTowardsIt.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/findNearestEnemyAndHeadTowardsIt.cpp @@ -35,7 +35,7 @@ namespace Map { int _bestScore = 100000; int _foundEnemyID = 0; int _visionDivisor = 1; - bool _skipStanceSearch = false; + int _skipStanceSearch = 0; int _stanceBasedRange = 0; short _isRallying = 0; if ((this->units[unitID].SA != 0 @@ -52,7 +52,7 @@ namespace Map { } } if (this->units[unitID].targetingType == OpenSHC::Map::Units::UIT_UNIT_ATTACK_UNIT) { - _skipStanceSearch = true; + _skipStanceSearch = 1; switch (this->units[unitID].unitType) { case OpenSHC::Map::Units::UT_TUNNELER: case OpenSHC::Map::Units::UT_E_SPEAR: @@ -65,13 +65,13 @@ namespace Map { case OpenSHC::Map::Units::UT_A_SLAVE: case OpenSHC::Map::Units::UT_A_ASSASSIN: case OpenSHC::Map::Units::UT_A_SWORDSMAN: - _skipStanceSearch = false; + _skipStanceSearch = 0; if (this->units[unitID].tribeID != 0) { int _tribeUnitID = DAT_TribesState::instance.tribes[this->units[unitID].tribeID].someUnitID; if (_tribeUnitID != 0 && this->units[_tribeUnitID].uid == DAT_TribesState::instance.tribes[this->units[unitID].tribeID].someUnitUID) { - _skipStanceSearch = true; + _skipStanceSearch = 1; break; } } @@ -106,11 +106,11 @@ namespace Map { } this->units[unitID].lookForEnemy = (short)_lookAhead; } - _skipStanceSearch = true; + _skipStanceSearch = 1; } } if (this->units[unitID].isSelectable_OR_matchTime == 0) { - _skipStanceSearch = true; + _skipStanceSearch = 1; } if (DAT_GameState::instance.playerDataArray[_playerID].enemies < 5) { _visionDivisor = 5; @@ -294,12 +294,12 @@ namespace Map { _foundEnemyID = _enemyUnitID; } } - bool _restoreSavedDestination = false; + int _restoreSavedDestination = 0; if (_stanceBasedRange == 0) { if (this->units[unitID].lookForEnemy == 0) { this->units[unitID].movementType_OR_targetUnitID = 0; if (this->units[unitID].state.generic == OpenSHC::Map::Units::States::US_MOVE_TO_DESTINATION) { - _restoreSavedDestination = true; + _restoreSavedDestination = 1; } } } else if (this->units[unitID].lookForEnemy >= 0) { @@ -307,11 +307,11 @@ namespace Map { if (this->units[unitID].lookForEnemy == 0) { this->units[unitID].movementType_OR_targetUnitID = 0; if (this->units[unitID].state.generic == OpenSHC::Map::Units::States::US_MOVE_TO_DESTINATION) { - _restoreSavedDestination = true; + _restoreSavedDestination = 1; } } } else { - bool _headedToEnemy = false; + int _headedToEnemy = 0; if (_foundEnemyID != 0 && MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func:: calculateCanPlayerUnitsNavigateToAreaFromArea, @@ -341,12 +341,12 @@ namespace Map { this->units[unitID].movementType_OR_targetUnitID = (short)_foundEnemyID; this->units[_foundEnemyID].huntedBy = this->units[_foundEnemyID].huntedBy + 1; } - _headedToEnemy = true; + _headedToEnemy = 1; } if (!_headedToEnemy) { this->units[unitID].lookForEnemy = -8; this->units[unitID].movementType_OR_targetUnitID = 0; - _restoreSavedDestination = true; + _restoreSavedDestination = 1; } } } diff --git a/src/OpenSHC/Map/Units/UnitsState/stopUnitIfNextToTarget.cpp b/src/OpenSHC/Map/Units/UnitsState/stopUnitIfNextToTarget.cpp index c6ba33796..99b62a41f 100644 --- a/src/OpenSHC/Map/Units/UnitsState/stopUnitIfNextToTarget.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/stopUnitIfNextToTarget.cpp @@ -17,12 +17,12 @@ namespace Map { return 0; } uint _tile = 0; - bool _isNear = false; + int _isNear = 0; for (int direction = 0; direction < 8; ++direction) { _tile = DAT_TileMapState::instance.directionTranslationMatrix[this->units[unitID].y][direction] + this->units[unitID].tile; if (_tile == this->units[unitID].targetedBuildingTile) { - _isNear = true; + _isNear = 1; break; } } @@ -38,7 +38,7 @@ namespace Map { + _neighbourTile == this->units[unitID].targetedBuildingTile) { _tile = _neighbourTile; - _isNear = true; + _isNear = 1; break; } } diff --git a/src/OpenSHC/Map/Units/UnitsState/updateUnitFadeAndVisibilityNearStructures.cpp b/src/OpenSHC/Map/Units/UnitsState/updateUnitFadeAndVisibilityNearStructures.cpp index cd21f5e89..383d4b867 100644 --- a/src/OpenSHC/Map/Units/UnitsState/updateUnitFadeAndVisibilityNearStructures.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/updateUnitFadeAndVisibilityNearStructures.cpp @@ -16,16 +16,16 @@ namespace Map { { int _tile = this->units[unitID].tile; uint _logicFlags = DAT_TileMapState::instance.LogicLayer[_tile]; - byte _gateFadeType = 0; - byte _towerFadeType = 0; - byte _fadeType = 0; - bool _isOnDefensiveStructure = false; + int _gateFadeType = 0; + int _towerFadeType = 0; + int _fadeType = 0; + int _isOnDefensiveStructure = 0; if (this->units[unitID].unknownCountdown_0x402 != 0) { this->units[unitID].unknownCountdown_0x402 = this->units[unitID].unknownCountdown_0x402 - 1; } if (DAT_TileMapState::instance.BuildingLayer[_tile] == 0) { if ((_logicFlags & 0x100) != 0) { - _isOnDefensiveStructure = true; + _isOnDefensiveStructure = 1; } } else { switch (DAT_BuildingsState::instance.buildings[DAT_TileMapState::instance.BuildingLayer[_tile]] From 10e6c098260fd989f0b46e3a9e8e44bd84c2a874 Mon Sep 17 00:00:00 2001 From: Gynt Date: Tue, 29 Sep 2026 02:02:32 +0200 Subject: [PATCH 295/299] cleanup: setDestinationForUnit holds a signed field in an int, at equal match _unitX held units[].x, a signed short, in a uint, so every later comparison against the int parameter x was done unsigned. int is the honest type. An exact tie at 36.1486%, as was widening the two parameter copies alongside it. This was an attempt at the FRAME mismatch diff_triage reports for this function (frame 8 on the original against 0x14 on ours, three stack slots only we have) and it did not shrink the frame. Recording the negative: unlike BYTE and the local width and signedness family, FRAME does not appear to be mechanically actionable. The namespace has exactly one instance of an unsigned local holding a signed field, so there is no batch here either -- the signedness defects came in clusters of width (18 short locals, 9 byte flags) while this direction is essentially absent. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01A4PvfebpUzaMXy93EutBjJ --- src/OpenSHC/Map/Units/UnitsState/setDestinationForUnit.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/setDestinationForUnit.cpp b/src/OpenSHC/Map/Units/UnitsState/setDestinationForUnit.cpp index d1eb1a4bf..6277738e8 100644 --- a/src/OpenSHC/Map/Units/UnitsState/setDestinationForUnit.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/setDestinationForUnit.cpp @@ -29,7 +29,7 @@ namespace Map { if (MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::unitIsInMoat, this)(unitID) != FALSE) { DAT_PathFindingState::instance.climbIsIllegal = 1; } - uint _unitX = this->units[unitID].x; + int _unitX = this->units[unitID].x; this->units[unitID].climbDataID = 0; this->units[unitID].destinationX_2Unk = (short)x; this->units[unitID].destinationY_2Unk = (short)y; From 584cf1401ce09f31e0ddc6cdd13d969719a4eadd Mon Sep 17 00:00:00 2001 From: Gynt Date: Tue, 29 Sep 2026 14:35:41 +0200 Subject: [PATCH 296/299] reimplement: reorder independent statements, 3 functions reorder_search.py hill-climbs the match by swapping statements that are provably independent of each other. MSVC decides register allocation partly from the order in which values become live, so the order of independent writes before a call changes which value is in which register at the call boundary. getFirstSelectedUnitID 30.8% -> 85.7% normalized 100% queueDisbandAndAttackCommand5Params 21.4% -> 50.0% three successive swaps updateMicroPosition 55.8% -> 64.6% All three are small functions that write several independent values before a call, which is exactly the boundary case the tool documents as its exception. On a small function the proportional effect is far larger than the "fraction of a point" the docs lead you to expect: getFirstSelectedUnitID''s swap is two writes to different fields, neither reading the other''s target, and it moved the function 55 points. queueDisbandAndAttackCommand5Params needed three swaps that each built on the last, 21.4 -> 35.7 -> 42.9 -> 50.0. A hill-climb finds that; reading the diff does not. Five of the eight functions swept found nothing, and the three that did were all in this shape. getEnemyUnitIDNearby, checkAnySelectedUnitCannotClimb, setupUnitSharingTileIDs and playHurtSFXForUnit have zero candidate swaps at all: the independence test excludes any statement containing a call, and dense control flow leaves it nothing to move. Namespace 74.99% -> 75.48%. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01A4PvfebpUzaMXy93EutBjJ --- src/OpenSHC/Map/Units/UnitsState/getFirstSelectedUnitID.cpp | 2 +- .../Units/UnitsState/queueDisbandAndAttackCommand5Params.cpp | 4 ++-- src/OpenSHC/Map/Units/UnitsState/updateMicroPosition.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/getFirstSelectedUnitID.cpp b/src/OpenSHC/Map/Units/UnitsState/getFirstSelectedUnitID.cpp index ee8a483c0..491e21bda 100644 --- a/src/OpenSHC/Map/Units/UnitsState/getFirstSelectedUnitID.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/getFirstSelectedUnitID.cpp @@ -14,8 +14,8 @@ namespace Map { // FUNCTION: STRONGHOLDCRUSADER 0x00535DF0 void UnitsState::getFirstSelectedUnitID(undefined4 param_1) { - DAT_GameSynchronyState::instance.DAT_GameCommandParam1 = DAT_TribesState::instance.DAT_CurrentTribeID; DAT_GameSynchronyState::instance.DAT_GameCommandParam0 = param_1; + DAT_GameSynchronyState::instance.DAT_GameCommandParam1 = DAT_TribesState::instance.DAT_CurrentTribeID; MACRO_CALL_MEMBER(OpenSHC::Synchrony::GameSynchronyState_Func::queueCommand, DAT_GameSynchronyState::ptr)( (GameCommandType)0x48); } diff --git a/src/OpenSHC/Map/Units/UnitsState/queueDisbandAndAttackCommand5Params.cpp b/src/OpenSHC/Map/Units/UnitsState/queueDisbandAndAttackCommand5Params.cpp index 0d827d249..17399790b 100644 --- a/src/OpenSHC/Map/Units/UnitsState/queueDisbandAndAttackCommand5Params.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/queueDisbandAndAttackCommand5Params.cpp @@ -14,11 +14,11 @@ namespace Map { void UnitsState::queueDisbandAndAttackCommand5Params(undefined4 param_1, UnitInstructionType instruction, undefined4 param_3, undefined4 param_4, undefined4 param_5) { + DAT_GameSynchronyState::instance.DAT_GameCommandParam4 = param_5; DAT_GameSynchronyState::instance.DAT_GameCommandParam1 = instruction; DAT_GameSynchronyState::instance.DAT_GameCommandParam0 = param_1; - DAT_GameSynchronyState::instance.DAT_GameCommandParam4 = param_5; - DAT_GameSynchronyState::instance.DAT_GameCommandParam2 = param_3; DAT_GameSynchronyState::instance.DAT_GameCommandParam3 = param_4; + DAT_GameSynchronyState::instance.DAT_GameCommandParam2 = param_3; MACRO_CALL_MEMBER(OpenSHC::Synchrony::GameSynchronyState_Func::queueCommand, DAT_GameSynchronyState::ptr)( OpenSHC::Commands::GCT_DISBAND_AND_ATTACK_UNITS); } diff --git a/src/OpenSHC/Map/Units/UnitsState/updateMicroPosition.cpp b/src/OpenSHC/Map/Units/UnitsState/updateMicroPosition.cpp index 5dcc3ef88..60f854fd5 100644 --- a/src/OpenSHC/Map/Units/UnitsState/updateMicroPosition.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/updateMicroPosition.cpp @@ -21,9 +21,9 @@ namespace Map { _microPartX = (7 - _microPartX) * 16; _microPartY = _microPartY * 2; break; + _microPartY = (7 - _microPartY) * 16; case 4: _microPartX = (7 - _microPartX) * 2; - _microPartY = (7 - _microPartY) * 16; break; case 6: _microPartY = (7 - _microPartY) * 2; From 95e8f0e06bed416e6cc9c09c3ff856be9e567112 Mon Sep 17 00:00:00 2001 From: Gynt Date: Tue, 29 Sep 2026 15:02:32 +0200 Subject: [PATCH 297/299] tools: give the batch build scripts build.bat PDB server fix build.bat gives each worktree its own _MSPDBSRV_ENDPOINT_ and kills its own mspdbsrv.exe before building. build_quiet.py --keep-going calls cmakew directly and syntax_check.py calls cl.exe directly, so neither inherited that, and a server already wedged before the build started survived build.bat kill and still failed with C1090. common.build_env derives the same endpoint name; common.kill_pdb_server stops only this worktree instance; build_quiet.py retries the build once after a C1090/C1033. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01NaSkbxngnm28vFqxp3wNZs (cherry picked from commit ac343b42f3beedeb55deb6a2afee2112c0f407ea) (cherry picked from commit e3aeaf783fe57f4baf1d4878767c1e2bc4f104a2) --- tools/reimplementation-helper/batch/README.md | 9 +++++- .../batch/build_quiet.py | 31 ++++++++++++++----- tools/reimplementation-helper/batch/common.py | 30 ++++++++++++++++++ .../batch/syntax_check.py | 5 +-- 4 files changed, 65 insertions(+), 10 deletions(-) diff --git a/tools/reimplementation-helper/batch/README.md b/tools/reimplementation-helper/batch/README.md index 0522aaded..328f2e01f 100644 --- a/tools/reimplementation-helper/batch/README.md +++ b/tools/reimplementation-helper/batch/README.md @@ -12,7 +12,7 @@ rewrite sources, because the Visual Studio bundled one is too old for `.clang-fo | Script | Purpose | |---|---| -| `build_quiet.py [--keep-going]` | `build.bat RelWithDebInfo OpenSHC.dll`, prints only errors and `BUILD_OK`/`BUILD_FAIL` (build.bat exits 0 even on errors). | +| `build_quiet.py [--keep-going]` | `build.bat RelWithDebInfo OpenSHC.dll`, prints only errors and `BUILD_OK`/`BUILD_FAIL` (build.bat exits 0 even on errors). Retries once on a PDB server error, see the note below. | | `syntax_check.py [substr...]` | `cl /Zs` every (matching) list file serially; finds all compile errors in one pass without linking. | | `reccmp_report.py [--run] pct\|save\|cmp\|diff` | Match % and *normalized* % (call/tail-jump targets and resolver addresses ignored) per function, snapshots, before/after comparison, compact asm diffs. | | `orig_asm.py NAME [--both\|--stats]` | The **original** instruction stream of one function (not the interleaved diff), in address order; `--stats` reports the tells that decide how to reimplement it: `mov reg, 0` (handwritten asm), frame pointer (built /Od), frame size, jump tables. | @@ -99,3 +99,10 @@ bugs that Ghidra had decompiled wrongly. - A file whose `// FUNCTION:` address has no reccmp entry is reported as `--` / skipped. Check the address against `src/precomp/addresses-SHC-3BB0A8C1.hpp`. - Sources are always written as UTF-8 with LF line endings. +- Every script that runs `cl.exe` sets this worktree's own `_MSPDBSRV_ENDPOINT_` + (`common.build_env`), the same name `build.bat` derives. `mspdbsrv.exe` is a per-user + singleton keyed on that endpoint and each worktree carries its own toolchain copy, so a + shared endpoint makes `cl.exe` talk to the wrong server and fail with + `fatal error C1090: PDB API call failed`. `build_quiet.py` retries once after stopping + this worktree's `mspdbsrv.exe` (`common.kill_pdb_server`, never other worktrees'), which + clears a server that was already wedged before the build started. diff --git a/tools/reimplementation-helper/batch/build_quiet.py b/tools/reimplementation-helper/batch/build_quiet.py index 4395f90e3..1d901b2e9 100644 --- a/tools/reimplementation-helper/batch/build_quiet.py +++ b/tools/reimplementation-helper/batch/build_quiet.py @@ -5,13 +5,19 @@ Prints BUILD_OK or BUILD_FAIL as the last line. build.bat exits 0 even on compile errors, so the log is scanned instead of trusting the exit code. --keep-going reruns the build with nmake /K to collect errors from more files. + +The build runs with this worktree's own _MSPDBSRV_ENDPOINT_ (see common.build_env), which is what +build.bat does too; --keep-going bypasses build.bat and would otherwise inherit whatever endpoint +happens to be set. A build that still dies with C1090/C1033 gets one retry after stopping this +worktree's mspdbsrv.exe, because a wedged PDB server survives the kill build.bat does up front. """ import argparse import re import subprocess +import sys -from common import TMP +from common import PDB_ERROR_RE, TMP, build_env, kill_pdb_server parser = argparse.ArgumentParser() parser.add_argument("--keep-going", action="store_true") @@ -19,14 +25,25 @@ args = parser.parse_args() log = TMP / "build.log" -with open(log, "w") as out: - subprocess.run(["cmd", "/c", r".\build.bat RelWithDebInfo OpenSHC.dll"], stdout=out, stderr=subprocess.STDOUT) -if args.keep_going: + + +def run_build(): with open(log, "w") as out: - subprocess.run(["cmd", "/c", r".\cmakew --build --preset RelWithDebInfo --target OpenSHC.dll -- /K"], - stdout=out, stderr=subprocess.STDOUT) + subprocess.run(["cmd", "/c", r".\build.bat RelWithDebInfo OpenSHC.dll"], + stdout=out, stderr=subprocess.STDOUT, env=build_env()) + if args.keep_going: + with open(log, "w") as out: + subprocess.run(["cmd", "/c", r".\cmakew --build --preset RelWithDebInfo --target OpenSHC.dll -- /K"], + stdout=out, stderr=subprocess.STDOUT, env=build_env()) + return log.read_text(errors="replace") + + +text = run_build() +if PDB_ERROR_RE.search(text): + print("note: PDB server error, stopping this worktree's mspdbsrv.exe and retrying", file=sys.stderr) + kill_pdb_server() + text = run_build() -text = log.read_text(errors="replace") errors = [line for line in text.splitlines() if re.search(r" error |warning C4700|warning C4715", line) and "U1077" not in line] for line in errors[:args.max]: diff --git a/tools/reimplementation-helper/batch/common.py b/tools/reimplementation-helper/batch/common.py index e5d5ca81a..b2ce66a3b 100644 --- a/tools/reimplementation-helper/batch/common.py +++ b/tools/reimplementation-helper/batch/common.py @@ -27,6 +27,36 @@ DIFF_JSON = Path("reccmp/dll/diff.json") FUNCTION_RE = re.compile(r"//\s*FUNCTION:\s*STRONGHOLDCRUSADER\s+(0x[0-9A-Fa-f]+)") +# ---------------------------------------------------------------- pdb server + +# mspdbsrv.exe is a per-user singleton keyed on _MSPDBSRV_ENDPOINT_, and every worktree carries its +# own copy of the toolchain. Sharing one endpoint makes cl.exe talk to whichever copy started first +# and fail with "fatal error C1090: PDB API call failed, error code '23'" (or C1033). build.bat +# derives this same name, so setting it here keeps the two in step and also covers the scripts that +# drive cl.exe or cmake directly instead of going through build.bat. +PDB_ENDPOINT = "openshc_" + ROOT.name +PDB_ERROR_RE = re.compile(r"fatal error C10(90|33)") + + +def build_env(): + """Environment for anything that runs cl.exe, with this worktree's PDB endpoint.""" + env = dict(os.environ) + env.setdefault("_MSPDBSRV_ENDPOINT_", PDB_ENDPOINT) + return env + + +def kill_pdb_server(): + """Stop this worktree's mspdbsrv.exe only. + + Killing every instance by image name takes down the PDB server of any other worktree that is + building at the same time and fails their build with the same C1090. + """ + subprocess.run(["powershell", "-NoProfile", "-Command", + "Get-Process mspdbsrv -ErrorAction SilentlyContinue | " + "Where-Object { $_.Path -like '%s*' } | " + "Stop-Process -Force -ErrorAction SilentlyContinue" + % str(ROOT).replace("'", "''")], + capture_output=True) def list_files(existing_only=True): diff --git a/tools/reimplementation-helper/batch/syntax_check.py b/tools/reimplementation-helper/batch/syntax_check.py index 5fde77df5..4f7212a9f 100644 --- a/tools/reimplementation-helper/batch/syntax_check.py +++ b/tools/reimplementation-helper/batch/syntax_check.py @@ -12,7 +12,7 @@ import subprocess import sys -from common import BUILD_DIR, ROOT, TMP, list_files +from common import BUILD_DIR, ROOT, TMP, build_env, list_files commands = json.loads((BUILD_DIR / "compile_commands.json").read_text()) template = next(c["command"] for c in commands if "OpenSHC.dll.dir" in c["command"]) @@ -30,7 +30,8 @@ bat = TMP / "syntax_check.bat" bat.write_text("\n".join(lines) + "\n") -result = subprocess.run(["cmd", "/c", str(bat.resolve())], capture_output=True, text=True) +result = subprocess.run(["cmd", "/c", str(bat.resolve())], capture_output=True, text=True, + env=build_env()) errors = [l for l in (result.stdout + result.stderr).splitlines() if " error " in l or "fatal" in l] for line in errors: print(re.sub(r"^.*src.OpenSHC.", "", line)[:260]) From 2583dc71aac105697efdd2b745abe71277d80bbe Mon Sep 17 00:00:00 2001 From: Gynt Date: Tue, 29 Sep 2026 15:39:54 +0200 Subject: [PATCH 298/299] reimplement: reorder six independent statements in updateUnits; 41.2% -> 42.7% reorder_search.py accepted 6 of 66 candidate swaps in round 1 and none in round 2. All six are writes to distinct targets with no read-after-write dependency between them; the one worth checking by hand takes the address of movementRunUpTime while the statement it swaps past writes field199_0x350, so there is no aliasing. The hit rate matches what the tool documents, one move in ten, and confirms how the payoff scales: getFirstSelectedUnitID 25 lines 1 swap +54.9 queueDisbandAndAttackCommand5Params 28 lines 3 swaps +28.6 updateMicroPosition 40 lines 1 swap +8.9 updateUnits 943 lines 6 swaps +1.5 Six times the accepted moves for a thirtieth of the gain. The rate is roughly constant; the value per move falls with function size, because one reordered instruction is a smaller share of the whole. So this lever belongs on small badly-matching functions -- which is exactly what rank_functions.py sorts to the bottom, since it ranks by lines x (1 - match). Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01A4PvfebpUzaMXy93EutBjJ --- src/OpenSHC/Map/Units/UnitsState/updateUnits.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/OpenSHC/Map/Units/UnitsState/updateUnits.cpp b/src/OpenSHC/Map/Units/UnitsState/updateUnits.cpp index e1ae2fb87..34ed3c442 100644 --- a/src/OpenSHC/Map/Units/UnitsState/updateUnits.cpp +++ b/src/OpenSHC/Map/Units/UnitsState/updateUnits.cpp @@ -74,8 +74,8 @@ namespace Map { DAT_GameState::instance.playerDataArray[7].healerCount = 0; DAT_GameState::instance.playerDataArray[8].healerCount = 0; this->unitCount = 0; - this->maxUnitCount = 0; DAT_CurrentUnitSlotID::instance = 1; + this->maxUnitCount = 0; do { _currentUnitID = DAT_CurrentUnitSlotID::instance; if (this->units[_currentUnitID].logicalState != OpenSHC::Map::Units::ULS_INVISIBLE) { @@ -160,10 +160,10 @@ namespace Map { .translationMatrix[_targetY] .addXgetTile + _targetX]))); - this->units[DAT_CurrentUnitSlotID::instance].state.generic - = OpenSHC::Map::Units::States::US_IDLEUnk; this->units[DAT_CurrentUnitSlotID::instance].destinationNeeded = OpenSHC::Map::Units::Pathfinding::DNE_DESTINATION_HAS_BEEN_SET; + this->units[DAT_CurrentUnitSlotID::instance].state.generic + = OpenSHC::Map::Units::States::US_IDLEUnk; _currentUnitID = DAT_CurrentUnitSlotID::instance; } else { this->units[_currentUnitID].state.generic @@ -180,8 +180,8 @@ namespace Map { && (DAT_TileMapState::instance.LogicLayer[this->units[_currentUnitID].tile] & 0x50000000U) != 0) { this->units[_currentUnitID].state.generic = OpenSHC::Map::Units::States::US_DISAPPEAR; - this->units[DAT_CurrentUnitSlotID::instance].updateTickTracker = 0; _currentUnitID = DAT_CurrentUnitSlotID::instance; + this->units[DAT_CurrentUnitSlotID::instance].updateTickTracker = 0; } } if (this->units[_currentUnitID].logicalState == OpenSHC::Map::Units::ULS_NORMAL @@ -619,10 +619,10 @@ namespace Map { if (7 < this->units[DAT_CurrentUnitSlotID::instance].movementRelated) { this->units[DAT_CurrentUnitSlotID::instance].logicalState = OpenSHC::Map::Units::ULS_TRANSITIONING; + this->units[DAT_CurrentUnitSlotID::instance].workplaceBuildingID_1 = 0; this->units[DAT_CurrentUnitSlotID::instance].unitTypeToChangeInto = OpenSHC::Map::Units::UT_PEASANT; this->units[DAT_CurrentUnitSlotID::instance].state_2 = 0; - this->units[DAT_CurrentUnitSlotID::instance].workplaceBuildingID_1 = 0; MACRO_CALL_MEMBER( OpenSHC::Map::Units::UnitsState_Func::clearHiddenFlagAndUpdatePosition, this)( DAT_CurrentUnitSlotID::instance); @@ -669,8 +669,8 @@ namespace Map { + (int)this->units[DAT_CurrentUnitSlotID::instance].stateBasedSpeed + (int)this->units[DAT_CurrentUnitSlotID::instance].moveDelay < _troopValue - this->units[DAT_CurrentUnitSlotID::instance].field199_0x350) { - this->units[DAT_CurrentUnitSlotID::instance].field199_0x350 = _troopValue; _shortFieldPtr = &this->units[DAT_CurrentUnitSlotID::instance].movementRunUpTime; + this->units[DAT_CurrentUnitSlotID::instance].field199_0x350 = _troopValue; if (this->units[DAT_CurrentUnitSlotID::instance].movementRunUpTime <= 0) { *_shortFieldPtr = 0; } else { From 2826353e6c2ab3761e2a762ec28cfb6a4a403fb1 Mon Sep 17 00:00:00 2001 From: Gynt Date: Tue, 29 Sep 2026 15:40:54 +0200 Subject: [PATCH 299/299] tools/batch: retry on a fresh PDB endpoint, not just a fresh server The cherry-picked fix recovers from a wedged mspdbsrv.exe by stopping this worktree''s instance and building again. C1090 has a second cause that recovery cannot reach: the endpoint name itself can wedge, outliving every mspdbsrv.exe that uses it, so retrying into the same name fails forever. Six consecutive builds failed that way here. Killing the server did not help, nor did deleting the PCH and both PDBs; the endpoint was correctly unique, not inherited from the environment, and the toolchain binaries matched a worktree that was building fine at that moment. The same tree then built first try under a different endpoint name, which is what identified the cause. build_quiet.py now takes a second retry on a fresh endpoint, and build_env() accepts an explicit one so a caller can pin it for a session. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01A4PvfebpUzaMXy93EutBjJ --- .../batch/build_quiet.py | 28 +++++++++++++++---- tools/reimplementation-helper/batch/common.py | 24 ++++++++++++++-- 2 files changed, 43 insertions(+), 9 deletions(-) diff --git a/tools/reimplementation-helper/batch/build_quiet.py b/tools/reimplementation-helper/batch/build_quiet.py index 1d901b2e9..5647d1ec3 100644 --- a/tools/reimplementation-helper/batch/build_quiet.py +++ b/tools/reimplementation-helper/batch/build_quiet.py @@ -8,8 +8,16 @@ The build runs with this worktree's own _MSPDBSRV_ENDPOINT_ (see common.build_env), which is what build.bat does too; --keep-going bypasses build.bat and would otherwise inherit whatever endpoint -happens to be set. A build that still dies with C1090/C1033 gets one retry after stopping this -worktree's mspdbsrv.exe, because a wedged PDB server survives the kill build.bat does up front. +happens to be set. A build that dies with C1090/C1033 gets two retries, because that error has two +different causes: + + 1. a wedged PDB server, which survives the kill build.bat does up front -> stop this worktree's + mspdbsrv.exe and build again; + 2. a wedged *endpoint*, which outlives every mspdbsrv.exe using it -> build again on a fresh + endpoint name, since retrying into the same name fails forever. + +The second cost six consecutive builds once, across a regenerated PCH and PDBs, while the same tree +built first try under a different endpoint name. """ import argparse @@ -17,7 +25,7 @@ import subprocess import sys -from common import PDB_ERROR_RE, TMP, build_env, kill_pdb_server +from common import PDB_ERROR_RE, TMP, build_env, fresh_pdb_endpoint, kill_pdb_server parser = argparse.ArgumentParser() parser.add_argument("--keep-going", action="store_true") @@ -27,14 +35,14 @@ log = TMP / "build.log" -def run_build(): +def run_build(endpoint=None): with open(log, "w") as out: subprocess.run(["cmd", "/c", r".\build.bat RelWithDebInfo OpenSHC.dll"], - stdout=out, stderr=subprocess.STDOUT, env=build_env()) + stdout=out, stderr=subprocess.STDOUT, env=build_env(endpoint)) if args.keep_going: with open(log, "w") as out: subprocess.run(["cmd", "/c", r".\cmakew --build --preset RelWithDebInfo --target OpenSHC.dll -- /K"], - stdout=out, stderr=subprocess.STDOUT, env=build_env()) + stdout=out, stderr=subprocess.STDOUT, env=build_env(endpoint)) return log.read_text(errors="replace") @@ -43,6 +51,14 @@ def run_build(): print("note: PDB server error, stopping this worktree's mspdbsrv.exe and retrying", file=sys.stderr) kill_pdb_server() text = run_build() +if PDB_ERROR_RE.search(text): + # The endpoint itself can be wedged, in which case it outlives every mspdbsrv.exe using it and + # retrying into the same name fails forever. Move to a fresh one. + endpoint = fresh_pdb_endpoint() + print("note: PDB endpoint still failing, retrying on a fresh endpoint %s" % endpoint, + file=sys.stderr) + kill_pdb_server() + text = run_build(endpoint) errors = [line for line in text.splitlines() if re.search(r" error |warning C4700|warning C4715", line) and "U1077" not in line] diff --git a/tools/reimplementation-helper/batch/common.py b/tools/reimplementation-helper/batch/common.py index b2ce66a3b..3e15e3d9d 100644 --- a/tools/reimplementation-helper/batch/common.py +++ b/tools/reimplementation-helper/batch/common.py @@ -38,10 +38,28 @@ PDB_ERROR_RE = re.compile(r"fatal error C10(90|33)") -def build_env(): - """Environment for anything that runs cl.exe, with this worktree's PDB endpoint.""" +def fresh_pdb_endpoint(): + """A previously unused endpoint name for this worktree. + + An endpoint can wedge in a way that outlives every mspdbsrv.exe using it: the name stays + unusable, and `cl.exe` keeps failing with C1090 no matter how often the server is killed and + restarted. Six consecutive builds failed that way once, across a fresh PCH and PDBs, while the + same tree built first try under a different name. So when killing the server does not help, + move to a new name rather than retrying into the same one. + """ + return "%s_%d" % (PDB_ENDPOINT, os.getpid()) + + +def build_env(endpoint=None): + """Environment for anything that runs cl.exe, with this worktree's PDB endpoint. + + An endpoint already set in the environment wins, so a caller can pin one for a whole session. + """ env = dict(os.environ) - env.setdefault("_MSPDBSRV_ENDPOINT_", PDB_ENDPOINT) + if endpoint: + env["_MSPDBSRV_ENDPOINT_"] = endpoint + else: + env.setdefault("_MSPDBSRV_ENDPOINT_", PDB_ENDPOINT) return env