Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
104 commits
Select commit Hold shift + click to select a range
ea22350
reimplement: OpenSHC::AI::AICState
gynt Sep 26, 2026
1ec6319
add status
gynt Sep 26, 2026
5dd535f
reimplement: SHC_3BB0A8C1_0x004D0580 100.00% Reimplemented
gynt Oct 1, 2026
7dcb33d
reimplement: SHC_3BB0A8C1_0x004CC520 100.00% Reimplemented
gynt Oct 1, 2026
e0c73b9
reimplement: SHC_3BB0A8C1_0x004CDB20 34.34% regalloc/spill differs
gynt Oct 1, 2026
899e3c8
reimplement: SHC_3BB0A8C1_0x004CC250 100.00% Reimplemented
gynt Oct 1, 2026
bb39059
reimplement: SHC_3BB0A8C1_0x004CB5B0 100.00% Reimplemented
gynt Oct 1, 2026
06716bc
reimplement: SHC_3BB0A8C1_0x004CB9F0 100.00% Reimplemented
gynt Oct 1, 2026
a6b3ea6
reimplement: SHC_3BB0A8C1_0x004CC8D0 100.00% Reimplemented
gynt Oct 1, 2026
c33b3f1
reimplement: SHC_3BB0A8C1_0x004D2000 32.00% loop bound fixed, asm dif…
gynt Oct 1, 2026
a84adc1
reimplement: SHC_3BB0A8C1_0x004CB940 100.00% Reimplemented
gynt Oct 1, 2026
bab6c5a
reimplement: SHC_3BB0A8C1_0x004CE930 91.25% regalloc differs
gynt Oct 1, 2026
fd38a27
reimplement: SHC_3BB0A8C1_0x004CC420 39.42% regalloc/locals differ
gynt Oct 1, 2026
11b2e1f
reimplement: SHC_3BB0A8C1_0x004D3AE0 36.88% stack layout now matches
gynt Oct 1, 2026
f561383
AICState: record the measured cost of the smallestTribeOfUnitType sha…
gynt Oct 1, 2026
c632c42
AICState: write setInitialAIC's qualified name without the stray space
gynt Oct 1, 2026
9288546
tools/batch: commit_progress_batch committed whatever else was staged
gynt Oct 1, 2026
dd20c8a
reimplement: SHC_3BB0A8C1_0x004D0F40 100.00% Reimplemented
gynt Oct 1, 2026
3ca8824
reimplement: SHC_3BB0A8C1_0x004D0E50 100.00% Reimplemented
gynt Oct 1, 2026
77bd87a
reimplement: SHC_3BB0A8C1_0x004D0EA0 100.00% Reimplemented
gynt Oct 1, 2026
2e89189
reimplement: SHC_3BB0A8C1_0x004D0EF0 100.00% Reimplemented
gynt Oct 1, 2026
b7d598c
reimplement: SHC_3BB0A8C1_0x004D0DB0 100.00% Reimplemented
gynt Oct 1, 2026
2b888a0
reimplement: SHC_3BB0A8C1_0x004D0E00 100.00% Reimplemented
gynt Oct 1, 2026
633c777
reimplement: SHC_3BB0A8C1_0x004CD070 100.00% Reimplemented
gynt Oct 1, 2026
0f4a8bd
reimplement: SHC_3BB0A8C1_0x004CCFB0 90.00% imported, regalloc differs
gynt Oct 1, 2026
25d8464
reimplement: SHC_3BB0A8C1_0x004CC390 63.16% imported, asm differs
gynt Oct 1, 2026
d7414b0
reimplement: SHC_3BB0A8C1_0x004CC390 79.49% block layout differs
gynt Oct 1, 2026
b1e26bc
reimplement: SHC_3BB0A8C1_0x004CC390 100.00% Reimplemented
gynt Oct 2, 2026
c3e4afb
reimplement: SHC_3BB0A8C1_0x004CFCD0 92.65% regalloc/addressing differs
gynt Oct 3, 2026
d19d189
reimplement: SHC_3BB0A8C1_0x004D3AE0 40.27% pointer-walk/regalloc dif…
gynt Oct 3, 2026
27bad64
cheat sheet: record three measured AI::AICState diff patterns
gynt Oct 3, 2026
e3a6a67
tools/batch: document that the two norm columns differ, and that diff…
gynt Oct 3, 2026
4a862db
reimplement: SHC_3BB0A8C1_0x004D2000 34.88% fixed siegeIndex>=2 skip
gynt Oct 4, 2026
d8637db
cheat sheet: statement order is not the lever for the setAICParameter…
gynt Oct 4, 2026
6487972
AICState: enable the resolvers aiBuyAndSellGoods tail-jumps to
gynt Oct 5, 2026
f2d3cc7
reimplement: SHC_3BB0A8C1_0x004CC680 100.00% Reimplemented
gynt Oct 5, 2026
8713a8d
reimplement: SHC_3BB0A8C1_0x004D2730 100.00% Reimplemented
gynt Oct 5, 2026
945c909
reimplement: SHC_3BB0A8C1_0x004CFCD0 99.36% reload order after call d…
gynt Oct 5, 2026
febd8d4
reimplement: SHC_3BB0A8C1_0x004CF470 100.00% Reimplemented
gynt Oct 5, 2026
3311de9
reimplement: SHC_3BB0A8C1_0x004CF2E0 83.44% esi/edi regalloc differs
gynt Oct 5, 2026
b96c093
reimplement: SHC_3BB0A8C1_0x004CF270 100.00% Reimplemented
gynt Oct 5, 2026
a326ba0
reimplement: SHC_3BB0A8C1_0x004CB3A0 100.00% Reimplemented
gynt Oct 5, 2026
93c3b58
reimplement: SHC_3BB0A8C1_0x004CC5A0 100.00% Reimplemented
gynt Oct 5, 2026
d37d5fd
reimplement: SHC_3BB0A8C1_0x004D2660 86.11% ebx/ebp regalloc differs
gynt Oct 5, 2026
4a5d9fe
reimplement: SHC_3BB0A8C1_0x004D3780 100.00% Reimplemented
gynt Oct 5, 2026
939df02
reimplement: SHC_3BB0A8C1_0x004D0280 100.00% Reimplemented
gynt Oct 5, 2026
2e43819
reimplement: SHC_3BB0A8C1_0x004D38C0 100.00% Reimplemented
gynt Oct 5, 2026
a405be0
reimplement: SHC_3BB0A8C1_0x004D3850 100.00% Reimplemented
gynt Oct 5, 2026
e30d4f4
reimplement: SHC_3BB0A8C1_0x004CE930 100.00% Reimplemented
gynt Oct 5, 2026
b0266c1
reimplement: SHC_3BB0A8C1_0x004CDBC0 100.00% Reimplemented
gynt Oct 5, 2026
65994b3
reimplement: SHC_3BB0A8C1_0x004CEA50 100.00% Reimplemented
gynt Oct 5, 2026
3764d7c
reimplement: SHC_3BB0A8C1_0x004CE430 100.00% Reimplemented
gynt Oct 5, 2026
7e9040d
reimplement: SHC_3BB0A8C1_0x004CF4F0 100.00% Reimplemented
gynt Oct 5, 2026
148c99a
reimplement: SHC_3BB0A8C1_0x004CF750 100.00% Reimplemented
gynt Oct 5, 2026
cf84238
reimplement: SHC_3BB0A8C1_0x004D30E0 100.00% Reimplemented
gynt Oct 5, 2026
3fc4aa3
reimplement: SHC_3BB0A8C1_0x004CDE60 100.00% Reimplemented
gynt Oct 5, 2026
3ad4530
reimplement: SHC_3BB0A8C1_0x004CF560 100.00% Reimplemented
gynt Oct 5, 2026
468e518
reimplement: SHC_3BB0A8C1_0x004CF400 100.00% Reimplemented
gynt Oct 5, 2026
922fa0c
reimplement: SHC_3BB0A8C1_0x004CF6E0 100.00% Reimplemented
gynt Oct 5, 2026
8b73082
tools/batch: quick_diff.py, and the source patterns it found in AI::A…
gynt Oct 5, 2026
a39914d
reimplement: SHC_3BB0A8C1_0x004C6D60 100.00% Reimplemented
gynt Oct 5, 2026
b28955a
reimplement: SHC_3BB0A8C1_0x004C7120 100.00% Reimplemented
gynt Oct 5, 2026
691050e
reimplement: SHC_3BB0A8C1_0x004C7520 100.00% Reimplemented
gynt Oct 5, 2026
6ae05f6
reimplement: SHC_3BB0A8C1_0x004C7910 100.00% Reimplemented
gynt Oct 5, 2026
15eba88
reimplement: SHC_3BB0A8C1_0x004C7D20 100.00% Reimplemented
gynt Oct 5, 2026
ae56163
reimplement: SHC_3BB0A8C1_0x004C8110 100.00% Reimplemented
gynt Oct 5, 2026
c41a4af
reimplement: SHC_3BB0A8C1_0x004C8530 100.00% Reimplemented
gynt Oct 5, 2026
7513c07
reimplement: SHC_3BB0A8C1_0x004C8920 100.00% Reimplemented
gynt Oct 5, 2026
5d11984
reimplement: SHC_3BB0A8C1_0x004C8D20 100.00% Reimplemented
gynt Oct 5, 2026
08ce404
reimplement: SHC_3BB0A8C1_0x004C9120 100.00% Reimplemented
gynt Oct 5, 2026
b15e74c
reimplement: SHC_3BB0A8C1_0x004C94F0 100.00% Reimplemented
gynt Oct 5, 2026
3cfa10d
reimplement: SHC_3BB0A8C1_0x004C9900 100.00% Reimplemented
gynt Oct 5, 2026
825bf1f
reimplement: SHC_3BB0A8C1_0x004C9CF0 100.00% Reimplemented
gynt Oct 5, 2026
42e5035
reimplement: SHC_3BB0A8C1_0x004CA0C0 100.00% Reimplemented
gynt Oct 5, 2026
2127339
reimplement: SHC_3BB0A8C1_0x004CA4D0 100.00% Reimplemented
gynt Oct 5, 2026
e2e6951
reimplement: SHC_3BB0A8C1_0x004CA8A0 100.00% Reimplemented
gynt Oct 5, 2026
fc674a0
reimplement: SHC_3BB0A8C1_0x004CCD20 66.03% frame and regalloc differ
gynt Oct 5, 2026
a2aa460
reimplement: SHC_3BB0A8C1_0x004CF2E0 94.74% esi/edi regalloc differs
gynt Oct 5, 2026
5c3a5d1
reimplement: SHC_3BB0A8C1_0x004D2000 39.43% frame size and regalloc d…
gynt Oct 5, 2026
f90e6a5
reimplement: SHC_3BB0A8C1_0x004D3AE0 41.60% regalloc differs
gynt Oct 5, 2026
bf2ba81
reimplement: SHC_3BB0A8C1_0x004CDB20 44.44% regalloc/spill differs
gynt Oct 5, 2026
007ee42
reimplement: SHC_3BB0A8C1_0x004CE200 64.52% spilled local differs
gynt Oct 5, 2026
5f8b29a
reimplement: SHC_3BB0A8C1_0x004CCAF0 100.00% Reimplemented
gynt Oct 5, 2026
2477b7d
reimplement: SHC_3BB0A8C1_0x004D1320 72.34% regalloc differs
gynt Oct 5, 2026
d35fab3
reimplement: SHC_3BB0A8C1_0x004D1D60 62.41% register permutation
gynt Oct 5, 2026
c71a847
reimplement: SHC_3BB0A8C1_0x004CC990 56.59% regalloc/locals differ
gynt Oct 5, 2026
a6678bf
reimplement: SHC_3BB0A8C1_0x004D3320 97.24% ebp/ebx regalloc differs
gynt Oct 5, 2026
fcfabd0
reimplement: SHC_3BB0A8C1_0x004D28B0 86.32% select call block layout …
gynt Oct 5, 2026
001f204
reimplement: SHC_3BB0A8C1_0x004D2660 100.00% Reimplemented
gynt Oct 5, 2026
b225b0f
reimplement: SHC_3BB0A8C1_0x004CD8F0 100.00% Reimplemented
gynt Oct 5, 2026
1b90c07
reimplement: SHC_3BB0A8C1_0x004CD7B0 100.00% Reimplemented
gynt Oct 5, 2026
f7e70f0
reimplement: SHC_3BB0A8C1_0x004CC420 100.00% Reimplemented
gynt Oct 5, 2026
f66c8f2
reimplement: SHC_3BB0A8C1_0x004D2A70 54.27% regalloc/spills differ
gynt Oct 6, 2026
595344f
reimplement: SHC_3BB0A8C1_0x004CDCF0 76.14% regalloc differs
gynt Oct 6, 2026
11e62c4
reimplement: SHC_3BB0A8C1_0x004D1320 72.34% Style pass, asm differs
gynt Oct 6, 2026
fb6fbbc
reimplement: SHC_3BB0A8C1_0x004CCFB0 100.00% Reimplemented
gynt Oct 6, 2026
e8717d9
reimplement: SHC_3BB0A8C1_0x004CFCD0 100.00% Reimplemented
gynt Oct 6, 2026
941e975
reimplement: SHC_3BB0A8C1_0x004CDCF0 77.16% regalloc/counters differ
gynt Oct 6, 2026
4151866
reimplement: SHC_3BB0A8C1_0x004D2000 40.62% regalloc/frame differ
gynt Oct 6, 2026
ad0fdef
reimplement: SHC_3BB0A8C1_0x004CBA50 90.73% flag slot order differs
gynt Oct 6, 2026
2849d33
reimplement: SHC_3BB0A8C1_0x004D3AE0 43.38% regalloc/spills differ
gynt Oct 6, 2026
d04e5b1
cheat sheet: what Ghidra's decompilation is and is not reliable for
gynt Oct 6, 2026
f75c623
reimplement: SHC_3BB0A8C1_0x004D2000 41.87% regalloc/frame differ
gynt Oct 6, 2026
f99565d
cheat sheet: correct the Ghidra note - measure restructurings with re…
gynt Oct 6, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
155 changes: 126 additions & 29 deletions IMPLEMENTATION_CHEAT_SHEET.md

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion cmake/compiler-flags-gl.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,5 @@ src/OpenSHC/Audio/SFX/SFXState/playUnitSpeech.cpp
src/OpenSHC/Game/GameStateStructures/getSellResourceAmount.cpp
src/OpenSHC/Map/TileMapState/determineBuildingPlacementRotation.cpp
src/OpenSHC/Map/Navigation/DirectionAlgorithmState/getMouseVectorLengthBasedOnDirection.cpp
src/OpenSHC/Input/MouseState/updateRightDragCameraControl.cpp
src/OpenSHC/Input/MouseState/updateRightDragCameraControl.cpp
src/OpenSHC/AI/AICState/planToBuyWhenLowOnResourceAndSnoozeBuildings.cpp
4 changes: 2 additions & 2 deletions src/OpenSHC/AI/AICState.func.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -631,7 +631,7 @@ namespace AI {
decideOnTribeAttackLocation;

MACRO_FUNCTION_RESOLVER(
void (AICState::*)(int), false, Address::SHC_3BB0A8C1_0x004D1D60, &AICState::sellExcessGoods)
void (AICState::*)(int), true, Address::SHC_3BB0A8C1_0x004D1D60, &AICState::sellExcessGoods)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fix

sellExcessGoods;

MACRO_FUNCTION_RESOLVER(void (AICState::*)(int, ResourceType, int), false, Address::SHC_3BB0A8C1_0x004D1F00,
Expand Down Expand Up @@ -715,7 +715,7 @@ namespace AI {
makeOutpostTribesAttack;

MACRO_FUNCTION_RESOLVER(
void (AICState::*)(int), false, Address::SHC_3BB0A8C1_0x004D39B0, &AICState::buyRequiredGoods)
void (AICState::*)(int), true, Address::SHC_3BB0A8C1_0x004D39B0, &AICState::buyRequiredGoods)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

fix

buyRequiredGoods;

MACRO_FUNCTION_RESOLVER(
Expand Down
14 changes: 14 additions & 0 deletions src/OpenSHC/AI/AICState/Constructor_AICState.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#include "../AICState.func.hpp"

namespace OpenSHC {
namespace AI {

// FUNCTION: STRONGHOLDCRUSADER 0x004D3940
AICState* AICState::Constructor_AICState()
{
MACRO_CALL_MEMBER(AICState_Func::setInitialAIC, this)();
this->aiTauntResponseTimeWindow = 0;
return this;
}
}
}
23 changes: 23 additions & 0 deletions src/OpenSHC/AI/AICState/abortAttackAndGoIdle.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#include "../AICState.func.hpp"

#include "OpenSHC/Map/Buildings/BuildingsState.func.hpp"

#include "OpenSHC/Globals/DAT_BuildingsState.hpp"
#include "OpenSHC/Globals/DAT_GameState.hpp"

namespace OpenSHC {
namespace AI {

// FUNCTION: STRONGHOLDCRUSADER 0x004D45E0
void AICState::abortAttackAndGoIdle(int playerID)
{
MACRO_CALL_MEMBER(Map::Buildings::BuildingsState_Func::removeSiegeBuildings, DAT_BuildingsState::ptr)(
DAT_GameState::instance.playerDataArray[playerID].currentAttackWave, playerID);
MACRO_CALL_MEMBER(AICState_Func::disbandAIPlayerSiegeUnits, this)(playerID);
MACRO_CALL_MEMBER(AICState_Func::addEngineersToTribe, this)(playerID);
MACRO_CALL_MEMBER(AICState_Func::aiReassignTunnelersToTribe, this)(playerID);
DAT_GameState::instance.playerDataArray[playerID].aiPlayerState = 0;
}

}
}
30 changes: 30 additions & 0 deletions src/OpenSHC/AI/AICState/addBuildingToTargetableBuildings.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#include "../AICState.func.hpp"

#include "OpenSHC/Game/GameMode.hpp"

#include "OpenSHC/Globals/DAT_BuildingsState.hpp"
#include "OpenSHC/Globals/DAT_GameState.hpp"
#include "OpenSHC/Globals/DAT_GameSynchronyState.hpp"

namespace OpenSHC {
namespace AI {

// FUNCTION: STRONGHOLDCRUSADER 0x004CDA50
void AICState::addBuildingToTargetableBuildings(int buildingID)
{
int owner = DAT_BuildingsState::instance.buildings[buildingID].owner;
if (DAT_GameSynchronyState::instance.currentGameMode == Game::GM_SOLITARY)
return;
if (DAT_GameState::instance.playerDataArray[owner].top100TargetableBuildingsTracker >= 100)
return;
if (DAT_BuildingsState::instance.buildings[buildingID].fireDuration != 0)
return;

DAT_GameState::instance.playerDataArray[owner]
.top100TargetableBuildings[DAT_GameState::instance.playerDataArray[owner].top100TargetableBuildingsTracker]
= buildingID;
DAT_GameState::instance.playerDataArray[owner].top100TargetableBuildingsTracker++;
}

}
}
44 changes: 44 additions & 0 deletions src/OpenSHC/AI/AICState/addEngineersToSelection.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#include "../AICState.func.hpp"

#include "OpenSHC/Map/Units/TribesState.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_TribesState.hpp"
#include "OpenSHC/Globals/DAT_UnitsState.hpp"

namespace OpenSHC {
namespace AI {

// FUNCTION: STRONGHOLDCRUSADER 0x004CC680
int AICState::addEngineersToSelection(int playerID, int unitCount)
{
int tribeID
= MACRO_CALL_MEMBER(Map::Units::TribesState_Func::createTribeForPlayer, DAT_TribesState::ptr)(playerID);
for (int unitID = 1; unitID < (int)DAT_UnitsState::instance.maxUnitCount; unitID++) {
if (unitCount <= 0)
break;
if (DAT_UnitsState::instance.units[unitID].logicalState != Map::Units::ULS_NORMAL)
continue;
if (DAT_UnitsState::instance.units[unitID].owner != playerID)
continue;
if (DAT_UnitsState::instance.units[unitID].dying != 0)
continue;
if (DAT_UnitsState::instance.units[unitID].unitType != Map::Units::UT_E_ENGINEER)
continue;
if (DAT_UnitsState::instance.units[unitID].aiUnitBehaviourType != 10)
continue;
if (DAT_UnitsState::instance.units[unitID].tribeID != 0)
continue;
if (DAT_UnitsState::instance.units[unitID].state.generic == Map::Units::States::US_STAND_UPUnk)
continue;

MACRO_CALL_MEMBER(Map::Units::TribesState_Func::addUnitToTribe, DAT_TribesState::ptr)(unitID, tribeID);
unitCount--;
}
return tribeID;
}

}
}
33 changes: 33 additions & 0 deletions src/OpenSHC/AI/AICState/addEngineersToTribe.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#include "../AICState.func.hpp"

#include "OpenSHC/Map/Units/UnitLogicState.hpp"
#include "OpenSHC/Map/Units/UnitType.hpp"

#include "OpenSHC/Globals/DAT_UnitsState.hpp"

namespace OpenSHC {
namespace AI {

// FUNCTION: STRONGHOLDCRUSADER 0x004D4040
void AICState::addEngineersToTribe(int playerID)
{
for (int unitID = 1; unitID < (int)DAT_UnitsState::instance.maxUnitCount; unitID++) {
if (DAT_UnitsState::instance.units[unitID].logicalState != Map::Units::ULS_NORMAL)
continue;
if (DAT_UnitsState::instance.units[unitID].owner != playerID)
continue;
if (DAT_UnitsState::instance.units[unitID].dying != 0)
continue;
if (DAT_UnitsState::instance.units[unitID].unitType != Map::Units::UT_E_ENGINEER)
continue;
if (DAT_UnitsState::instance.units[unitID].aiUnitBehaviourType != 10)
continue;
if (DAT_UnitsState::instance.units[unitID].tribeID != 0)
continue;

MACRO_CALL_MEMBER(AICState_Func::addUnitToItsTribe, this)(unitID, 10);
}
}

}
}
57 changes: 57 additions & 0 deletions src/OpenSHC/AI/AICState/addRallyPointForTribe.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#include "../AICState.func.hpp"

#include "OpenSHC/Game/GameStateStructures.func.hpp"
#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp"
#include "OpenSHC/Map/Units/UnitLogicState.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_TribesState.hpp"
#include "OpenSHC/Globals/DAT_UnitsState.hpp"

namespace OpenSHC {
namespace AI {

// FUNCTION: STRONGHOLDCRUSADER 0x004CFA10
void AICState::addRallyPointForTribe(int tribeID)
{
DAT_TribesState::instance.tribes[tribeID].rallyPointCount = 0;
for (int unitID = 1; unitID < 2500; unitID++) {
if (DAT_UnitsState::instance.units[unitID].logicalState == OpenSHC::Map::Units::ULS_INVISIBLE)
continue;
if (MACRO_CALL_MEMBER(OpenSHC::Game::GameStateStructures_Func::getTeamsDifferent, DAT_GameState::ptr)(
DAT_TribesState::instance.tribes[tribeID].owner, DAT_UnitsState::instance.units[unitID].owner)
!= FALSE)
continue;
if (DAT_UnitsState::instance.units[unitID].unitType != OpenSHC::Map::Units::UT_S_CATAPULT
&& DAT_UnitsState::instance.units[unitID].unitType != OpenSHC::Map::Units::UT_S_TREBUCHET
&& DAT_UnitsState::instance.units[unitID].unitType != OpenSHC::Map::Units::UT_S_FBALLISTA)
continue;
if (DAT_UnitsState::instance.units[unitID].unknownSiegeTentRelated02 != 3)
continue;

MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::computeNextRallyPointDestination,
DAT_PathFindingState::ptr)(
-1, DAT_UnitsState::instance.units[unitID].x, DAT_UnitsState::instance.units[unitID].y);
DAT_TribesState::instance.tribes[tribeID]
.rallyPointArray[DAT_TribesState::instance.tribes[tribeID].rallyPointCount][0]
= DAT_PathFindingState::instance.ALG_ResultX;
DAT_TribesState::instance.tribes[tribeID]
.rallyPointArray[DAT_TribesState::instance.tribes[tribeID].rallyPointCount][1]
= DAT_PathFindingState::instance.ALG_ResultY;
DAT_TribesState::instance.tribes[tribeID].rallyPointCount++;
if (DAT_TribesState::instance.tribes[tribeID].rallyPointCount >= 9)
break;
}

if (DAT_TribesState::instance.tribes[tribeID].currentRallyPointIndex < 0)
DAT_TribesState::instance.tribes[tribeID].currentRallyPointIndex = 0;
if (DAT_TribesState::instance.tribes[tribeID].currentRallyPointIndex
>= DAT_TribesState::instance.tribes[tribeID].rallyPointCount)
DAT_TribesState::instance.tribes[tribeID].currentRallyPointIndex = 0;
}

}
}
27 changes: 27 additions & 0 deletions src/OpenSHC/AI/AICState/addUnitToItsTribe.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#include "../AICState.func.hpp"

#include "OpenSHC/Map/Units/TribesState.func.hpp"
#include "OpenSHC/AI/AITypeA.hpp"

#include "OpenSHC/Globals/DAT_GameState.hpp"
#include "OpenSHC/Globals/DAT_TribesState.hpp"
#include "OpenSHC/Globals/DAT_UnitsState.hpp"

namespace OpenSHC {
namespace AI {

// FUNCTION: STRONGHOLDCRUSADER 0x004D27E0
void AICState::addUnitToItsTribe(int unitID, int aiUnitBehaviourType)
{
int owner = DAT_UnitsState::instance.units[unitID].owner;
if (DAT_GameState::instance.playerDataArray[owner].aiType == AITA_NULL)
return;

DAT_UnitsState::instance.units[unitID].aiUnitBehaviourType = aiUnitBehaviourType;
int tribeID = MACRO_CALL_MEMBER(AICState_Func::addUnitToSmallestBehaviourTypeTribe, this)(
owner, unitID, aiUnitBehaviourType);
if (tribeID != 0)
MACRO_CALL_MEMBER(Map::Units::TribesState_Func::addUnitToTribe, DAT_TribesState::ptr)(unitID, tribeID);
}
}
}
82 changes: 82 additions & 0 deletions src/OpenSHC/AI/AICState/addUnitToSmallestBehaviourTypeTribe.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
#include "OpenSHC/Map/Units/TribesState.func.hpp"
#include "OpenSHC/AI/AICState.hpp"
#include "OpenSHC/AI/AITypeA.hpp"

#include "OpenSHC/Globals/DAT_GameState.hpp"
#include "OpenSHC/Globals/DAT_SkirmishDefinedData.hpp"
#include "OpenSHC/Globals/DAT_TribesState.hpp"

namespace OpenSHC {
namespace AI {

// FUNCTION: STRONGHOLDCRUSADER 0x004CCD20
int AICState::addUnitToSmallestBehaviourTypeTribe(
undefined4 playerID, undefined4 unitID, undefined4 aiUnitBehaviourType)
{
int aiType = DAT_GameState::instance.playerDataArray[playerID].aiType;
if (aiType == AITA_NULL)
return 0;

int aicIndex = aiType - 1;
int groupsCount;
switch (DAT_SkirmishDefinedData::instance.AIUnitBehaviourTypeMapping[aiUnitBehaviourType - 10]) {
case 15:
groupsCount = this->aics[aicIndex].AttUnitPatrolGroupsCount;
break;
case 186:
groupsCount = this->aics[aicIndex].AttUnitBackupGroupsCount;
break;
case 190:
groupsCount = this->aics[aicIndex].AttUnitSiegeDefGroupsCount;
break;
case 192:
groupsCount = this->aics[aicIndex].AttMainGroupsCount;
break;
default:
groupsCount = 1;
break;
}

int selectedTribeID = 0;
int selectedSlot = 0;
if (groupsCount <= 1) {
int tribeID = DAT_GameState::instance.playerDataArray[playerID].aiTribeIDs[DAT_SkirmishDefinedData::instance
.AIUnitBehaviourTypeMapping[aiUnitBehaviourType - 10]];
if (tribeID != 0
&& DAT_TribesState::instance.tribes[tribeID].uid
== DAT_GameState::instance.playerDataArray[playerID].aiTribeUIDs[DAT_SkirmishDefinedData::instance
.AIUnitBehaviourTypeMapping[aiUnitBehaviourType - 10]])
return tribeID;
selectedTribeID
= MACRO_CALL_MEMBER(Map::Units::TribesState_Func::createTribeForPlayer, DAT_TribesState::ptr)(playerID);
selectedSlot = DAT_SkirmishDefinedData::instance.AIUnitBehaviourTypeMapping[aiUnitBehaviourType - 10];
} else {
int smallestSize = 1000;
for (int slot = DAT_SkirmishDefinedData::instance.AIUnitBehaviourTypeMapping[aiUnitBehaviourType - 10]; slot
< DAT_SkirmishDefinedData::instance.AIUnitBehaviourTypeMapping[aiUnitBehaviourType - 10] + groupsCount;
slot++) {
int tribeID = DAT_GameState::instance.playerDataArray[playerID].aiTribeIDs[slot];
if (tribeID == 0
|| DAT_TribesState::instance.tribes[tribeID].uid
!= DAT_GameState::instance.playerDataArray[playerID].aiTribeUIDs[slot]) {
selectedTribeID = MACRO_CALL_MEMBER(
Map::Units::TribesState_Func::createTribeForPlayer, DAT_TribesState::ptr)(playerID);
selectedSlot = slot;
break;
}
if (DAT_TribesState::instance.tribes[tribeID].size < smallestSize) {
smallestSize = DAT_TribesState::instance.tribes[tribeID].size;
selectedTribeID = tribeID;
selectedSlot = slot;
}
}
}
if (selectedTribeID <= 0)
return 0;
DAT_GameState::instance.playerDataArray[playerID].aiTribeIDs[selectedSlot] = selectedTribeID;
DAT_GameState::instance.playerDataArray[playerID].aiTribeUIDs[selectedSlot]
= DAT_TribesState::instance.tribes[selectedTribeID].uid;
return selectedTribeID;
}
}
}
27 changes: 27 additions & 0 deletions src/OpenSHC/AI/AICState/addUnitToSmallestPatrolTribe.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#include "../AICState.func.hpp"

#include "OpenSHC/Map/Units/TribesState.func.hpp"
#include "OpenSHC/AI/AITypeA.hpp"

#include "OpenSHC/Globals/DAT_GameState.hpp"
#include "OpenSHC/Globals/DAT_TribesState.hpp"
#include "OpenSHC/Globals/DAT_UnitsState.hpp"

namespace OpenSHC {
namespace AI {

// FUNCTION: STRONGHOLDCRUSADER 0x004D2730
void AICState::addUnitToSmallestPatrolTribe(int unitID)
{
int owner = DAT_UnitsState::instance.units[unitID].owner;
if (DAT_GameState::instance.playerDataArray[owner].aiType == AITA_NULL)
return;
int aicIndex = DAT_GameState::instance.playerDataArray[owner].aiType - 1;

DAT_UnitsState::instance.units[unitID].aiUnitBehaviourType = 4;
int tribeID = MACRO_CALL_MEMBER(AICState_Func::getSmallestPatrolTribe, this)(
owner, this->aics[aicIndex].OuterPatrolGroupsCount);
MACRO_CALL_MEMBER(Map::Units::TribesState_Func::addUnitToTribe, DAT_TribesState::ptr)(unitID, tribeID);
}
}
}
Loading