Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
126 commits
Select commit Hold shift + click to select a range
cd47125
reimplement OpenSHC::AI::AICState: first pass
Jul 19, 2026
10a9b3d
pass 2
Jul 19, 2026
11e30f4
processed ghidra changes
Jul 19, 2026
dfbd12a
more rough unchecked reimplementations
Jul 19, 2026
3c1a7c4
batch 4 unpolished
gynt Jul 20, 2026
c946f8c
batch 5 unpolished
gynt Jul 20, 2026
d9d9fd6
clang-formatting
gynt Jul 20, 2026
ccdcdb7
ghidra-cpp and claude fixes
Jul 26, 2026
9e5eb41
fit improvements
Jul 27, 2026
8b73c02
better or worse
Jul 28, 2026
dd6fa45
param change
Jul 28, 2026
07f71d2
improvements
Jul 28, 2026
c6d5282
field name updates
Jul 29, 2026
80d83ca
improve readability and fit
Jul 29, 2026
62ab83f
as best as we can
Jul 29, 2026
3894bd2
improve rally percentage
Jul 29, 2026
6f04e8f
OpenSHC::AI::AICState::aiChoiceAttForceRallyPercentage 100%
Jul 29, 2026
dc57850
slow improvement
Jul 29, 2026
e25f2bf
slow improvement
Jul 29, 2026
bc820af
integrate main
Aug 3, 2026
2cf4d82
sellExcessGoods 61.18%
Aug 4, 2026
a5fac8e
fix typo
Aug 4, 2026
4b318e0
improve setAICParameters_01
Aug 16, 2026
c052859
improve setAICParameters
Aug 16, 2026
970160c
improve setAICParameters
Aug 17, 2026
f980592
reimplement OpenSHC::AI::AICState: first pass
Jul 19, 2026
dffaee5
pass 2
Jul 19, 2026
9c02a5f
processed ghidra changes
Jul 19, 2026
296d688
more rough unchecked reimplementations
Jul 19, 2026
183a4b7
batch 4 unpolished
gynt Jul 20, 2026
fe39181
batch 5 unpolished
gynt Jul 20, 2026
67e7178
clang-formatting
gynt Jul 20, 2026
48b4f4c
ghidra-cpp and claude fixes
Jul 26, 2026
66adddd
fit improvements
Jul 27, 2026
6a6f65d
better or worse
Jul 28, 2026
c2f1992
param change
Jul 28, 2026
0f55941
improvements
Jul 28, 2026
8e9929f
field name updates
Jul 29, 2026
bf7676c
improve readability and fit
Jul 29, 2026
bbed0b4
as best as we can
Jul 29, 2026
10f3336
improve rally percentage
Jul 29, 2026
42c8433
OpenSHC::AI::AICState::aiChoiceAttForceRallyPercentage 100%
Jul 29, 2026
303af56
slow improvement
Jul 29, 2026
e292459
slow improvement
Jul 29, 2026
0ce80ca
integrate main
Aug 3, 2026
25382f3
sellExcessGoods 61.18%
Aug 4, 2026
4f4f4d4
fix typo
Aug 4, 2026
df31b36
improve setAICParameters_01
Aug 16, 2026
0643abf
improve setAICParameters
Aug 16, 2026
84f90bf
improve setAICParameters
Aug 17, 2026
46e45fc
progress
gynt Sep 17, 2026
8de227d
reimplement: SHC_3BB0A8C1_0x004CF180 100%
gynt Sep 17, 2026
fbe8032
reimplement: SHC_3BB0A8C1_0x004CEFD0 100%
gynt Sep 17, 2026
fae9941
reimplement: SHC_3BB0A8C1_0x004D4940 100%
gynt Sep 17, 2026
438ae43
reimplement: SHC_3BB0A8C1_0x004D3320 87.69%, effectively 100%
gynt Sep 17, 2026
3b3f72f
Merge branch 'reimpl/AICState' of https://github.com/sourcehold/opens…
Sep 17, 2026
0b8e107
reimplement: SHC_3BB0A8C1_0x004D49E0 52.84%
Sep 17, 2026
badb10d
reimplement: SHC_3BB0A8C1_0x004D53E0 100%
Sep 17, 2026
63c9ce9
reimplement: SHC_3BB0A8C1_0x004CC8D0 100%
Sep 17, 2026
1d7d1df
reimplement: SHC_3BB0A8C1_0x004D0190 100%
Sep 17, 2026
d9a9c07
reimplement: SHC_3BB0A8C1_0x004D10B0 100%
Sep 17, 2026
bf62798
progress
Sep 17, 2026
a6fa273
reimplement: SHC_3BB0A8C1_0x004CC990 40.90%
Sep 19, 2026
c904f44
reimplement: SHC_3BB0A8C1_0x004CB610 100%
Sep 19, 2026
11aaf6a
reimplement: SHC_3BB0A8C1_0x004CB890 100%
Sep 19, 2026
80fb2e4
style improvement
Sep 19, 2026
88e8bfc
reimplement: SHC_3BB0A8C1_0x004D05D0 100%
Sep 19, 2026
a66c257
reimplement: SHC_3BB0A8C1_0x004CBE30 100%
Sep 19, 2026
4a6ad95
reimplement: SHC_3BB0A8C1_0x004CF400 62.22%
Sep 19, 2026
f1faa41
reimplement: SHC_3BB0A8C1_0x004CF6E0 SHC_3BB0A8C1_0x004CF560 differen…
Sep 19, 2026
78bdf23
reimplement: SHC_3BB0A8C1_0x004CACB0 100%
Sep 19, 2026
0d5a71b
reimplement: SHC_3BB0A8C1_0x004CE3B0 100%
Sep 19, 2026
b56a91b
improve style
gynt Sep 21, 2026
07d6280
reimplement: SHC_3BB0A8C1_0x004D18B0 100%
gynt Sep 21, 2026
e524977
reimplement: SHC_3BB0A8C1_0x004CF5E0 100%
gynt Sep 21, 2026
5a37488
reimplement: SHC_3BB0A8C1_0x004CDE60 76.09% stuck
gynt Sep 21, 2026
d1102ca
reimplement: SHC_3BB0A8C1_0x004CDF10 72.00% stuck
gynt Sep 21, 2026
a58ef14
reimplement: SHC_3BB0A8C1_0x004CDFD0 100%
gynt Sep 21, 2026
c7a2912
reimplement: SHC_3BB0A8C1_0x004D4340 54.63% stuck
gynt Sep 21, 2026
4d5e7fd
reimplement: SHC_3BB0A8C1_0x004CE5F0 100%
gynt Sep 21, 2026
35980a6
reimplement: SHC_3BB0A8C1_0x004CD0C0 100%
gynt Sep 21, 2026
6d5169f
reimplement: SHC_3BB0A8C1_0x004CD110 100%
gynt Sep 21, 2026
68648d5
reimplement: SHC_3BB0A8C1_0x004CF750 100%
gynt Sep 21, 2026
971e0ca
reimplement: SHC_3BB0A8C1_0x004D30E0 100%
gynt Sep 21, 2026
44bd0e1
reimplement: SHC_3BB0A8C1_0x004D2E00 100%
gynt Sep 21, 2026
ff0a34d
reimplement: SHC_3BB0A8C1_0x004D2870 100%
gynt Sep 21, 2026
969c7eb
reimplement: SHC_3BB0A8C1_0x004D4130 100%
gynt Sep 21, 2026
b2baeb3
reimplement: SHC_3BB0A8C1_0x004D44E0 100%
gynt Sep 21, 2026
7f8c964
reimplement: SHC_3BB0A8C1_0x004D4220 100%
gynt Sep 21, 2026
7898e1c
reimplement: SHC_3BB0A8C1_0x004CF4F0 57.10% stuck
gynt Sep 21, 2026
94f898c
reimplement: SHC_3BB0A8C1_0x004D1D60 52.50% stuck
gynt Sep 21, 2026
ef96b35
reimplement: SHC_3BB0A8C1_0x004CDCA0 100.0%
gynt Sep 21, 2026
63c5f11
reimplement: SHC_3BB0A8C1_0x004CDAB0 100%
gynt Sep 21, 2026
482fa2c
reimplement: SHC_3BB0A8C1_0x004D4680 64.80%
gynt Sep 21, 2026
ebcf32e
reimplement: SHC_3BB0A8C1_0x004D1F00 100%
gynt Sep 21, 2026
e068437
reimplement: SHC_3BB0A8C1_0x004D1320 69.88% stuck
gynt Sep 21, 2026
d984845
reimplement: SHC_3BB0A8C1_0x004CE430 100%
gynt Sep 22, 2026
519d47c
reimplement: SHC_3BB0A8C1_0x004CD2A0 59.60% block ordering problem
gynt Sep 22, 2026
180492a
reimplement: SHC_3BB0A8C1_0x004D4630 100% improve style
gynt Sep 22, 2026
b1c7425
reimplement: SHC_3BB0A8C1_0x004CE110 100%
gynt Sep 22, 2026
a2fe0aa
reimplement: SHC_3BB0A8C1_0x004CE040 100%
gynt Sep 22, 2026
77d9f24
reimplement: SHC_3BB0A8C1_0x004CE1A0 100%
gynt Sep 22, 2026
d09996f
progress
gynt Sep 22, 2026
87b3787
reimplement: SHC_3BB0A8C1_0x004CC070 100%
gynt Sep 22, 2026
6ad9b60
reimplement: SHC_3BB0A8C1_0x004CEEA0 100%
gynt Sep 22, 2026
8f428be
reimplement: SHC_3BB0A8C1_0x004D0C70 100%
gynt Sep 22, 2026
8a8ac98
reimplement: SHC_3BB0A8C1_0x004D0A80 100%
gynt Sep 22, 2026
9466c0b
reimplement: SHC_3BB0A8C1_0x004D1000 100% Reimplemented
gynt Sep 22, 2026
2f469f2
reimplement: SHC_3BB0A8C1_0x004D07C0 100% Reimplemented
gynt Sep 22, 2026
18d81a7
reimplement: SHC_3BB0A8C1_0x004D0D40 100% Reimplemented
gynt Sep 22, 2026
79aedd0
reimplement: SHC_3BB0A8C1_0x004D1050 100% Reimplemented
gynt Sep 22, 2026
d6f2953
reimplement: SHC_3BB0A8C1_0x004D0B10 68% Reimplemented functionally, …
gynt Sep 22, 2026
a2f086c
reimplement: SHC_3BB0A8C1_0x004D0D40 100% Reimplemented
gynt Sep 22, 2026
2667f90
reimplement: SHC_3BB0A8C1_0x004D08B0 100% Reimplemented
gynt Sep 22, 2026
c1e6390
reimplement: SHC_3BB0A8C1_0x004D1050 100% Reimplemented
gynt Sep 22, 2026
9b79e34
reimplement: SHC_3BB0A8C1_0x004D0830 100% Reimplemented
gynt Sep 22, 2026
0e6631e
reimplement: SHC_3BB0A8C1_0x004D0C00 100% Reimplemented
gynt Sep 22, 2026
1619d51
reimplement: SHC_3BB0A8C1_0x004D0FC0 100% Reimplemented
gynt Sep 22, 2026
4bf4be4
reimplement: SHC_3BB0A8C1_0x004D0B70 100% Reimplemented
gynt Sep 22, 2026
8a90902
reimplement: SHC_3BB0A8C1_0x004D0A20 100% Reimplemented
gynt Sep 22, 2026
56a08df
reimplement: SHC_3BB0A8C1_0x004D0BB0 100% Reimplemented
gynt Sep 22, 2026
3fa8fb6
reimplement: SHC_3BB0A8C1_0x004D0F90 100% Reimplemented
gynt Sep 22, 2026
241a028
reimplement: SHC_3BB0A8C1_0x004D0CF0 100% Reimplemented
gynt Sep 22, 2026
46e2a9e
reimplement: SHC_3BB0A8C1_0x004D0B10 68% Register scheduling issued
gynt Sep 22, 2026
e7c49bc
reimplement: SHC_3BB0A8C1_0x004CBA50 85.1% Reimplemented functionally…
gynt Sep 22, 2026
f5d8aad
reimplement: SHC_3BB0A8C1_0x004CED90 100% Reimplemented
gynt Sep 22, 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
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;
}

}
}
24 changes: 24 additions & 0 deletions src/OpenSHC/AI/AICState/addBuildingToTargetableBuildings.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#include "../AICState.func.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 _player = DAT_BuildingsState::instance.buildings[buildingID].owner;
if (DAT_GameSynchronyState::instance.DAT_CurrentGameMode != Game::GM_SOLITARY) {
int* piVar1 = &DAT_GameState::instance.playerDataArray[_player].top100TargetableBuildingsTracker;
if ((*piVar1 < 100) && (DAT_BuildingsState::instance.buildings[buildingID].fireDuration == 0)) {
DAT_GameState::instance.playerDataArray[_player].top100TargetableBuildings[*piVar1] = (short)buildingID;
*piVar1 = *piVar1 + 1;
}
}
}

}
}
45 changes: 45 additions & 0 deletions src/OpenSHC/AI/AICState/addEngineersToSelection.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#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/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;
uint unitID;

tribeID = MACRO_CALL_MEMBER(Map::Units::TribesState_Func::createTribeForPlayer, DAT_TribesState::ptr)(playerID);
unitID = 1;
if (1 < (int)DAT_UnitsState::instance.maxUnitCount) {
/* Unit offset 150 */
Map::Units::Unit* _ptrUnit = &DAT_UnitsState::instance.units[1];
do {
if (unitCount <= 0) {
return tribeID;
}
if ((((_ptrUnit->logicalState == Map::Units::ULS_NORMAL) && (_ptrUnit->owner == playerID))
&& (_ptrUnit->dying == 0))
&& (((_ptrUnit->unitType == Map::Units::UT_E_ENGINEER) && (_ptrUnit->aiUnitBehaviourType == 10))
&& ((_ptrUnit->tribeID == 0)
&& ((_ptrUnit->state).generic != Map::Units::States::US_STAND_UPUnk)))) {
MACRO_CALL_MEMBER(Map::Units::TribesState_Func::addUnitToTribe, DAT_TribesState::ptr)(
unitID, tribeID);
unitCount = unitCount + -1;
}
unitID = unitID + 1;
_ptrUnit = _ptrUnit + 1;
} while ((int)unitID < (int)DAT_UnitsState::instance.maxUnitCount);
}
return tribeID;
}

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

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

#include "OpenSHC/Globals/DAT_UnitsState.hpp"

namespace OpenSHC {
namespace AI {

// FUNCTION: STRONGHOLDCRUSADER 0x004D4040
void AICState::addEngineersToTribe(int playerID)
{
int _unitID = 1;
if (1 < (int)DAT_UnitsState::instance.maxUnitCount) {
Map::Units::Unit* _pUnit = &DAT_UnitsState::instance.units[1];
do {
/* if logicalState == normal && owner == playerID && unitType == 0x1e (engineer)
&& aiUnitBehaviourType == 10 */
if ((((_pUnit->logicalState == Map::Units::ULS_NORMAL) && (_pUnit->owner == playerID))
&& (_pUnit->dying == 0))
&& (((_pUnit->unitType == Map::Units::UT_E_ENGINEER) && (_pUnit->aiUnitBehaviourType == 10))
&& (_pUnit->tribeID == 0))) {
MACRO_CALL_MEMBER(AICState_Func::addUnitToItsTribe, this)(_unitID, 10);
}
_unitID = _unitID + 1;
_pUnit = _pUnit + 1;
} while (_unitID < (int)DAT_UnitsState::instance.maxUnitCount);
}
}

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

#include "OpenSHC/Game/GameStateStructures.func.hpp"
#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp"
#include "OpenSHC/Map/Units/Unit.hpp"
#include "OpenSHC/Map/Units/UnitLogicState.hpp"
#include "OpenSHC/Map/Units/UnitType.hpp"
#include "OpenSHC/Map/Units/UnitTypeShort.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 {

using OpenSHC::Map::Units::Unit;
using OpenSHC::Map::Units::UnitLogicState;
using OpenSHC::Map::Units::UnitType;
using OpenSHC::Map::Units::UnitTypeShort;
using OpenSHC::WindowsHelper::Enums::BOOLEnum;

/*
decompilerscript: committed: 2025-01-30 21:57:43.216000 */

// FUNCTION: STRONGHOLDCRUSADER 0x004CFA10
void AICState ::addRallyPointForTribe(int tribeID)

{

short* psVar1;

BOOLEnum _areInDifferentTeamsUnk;

Unit* _ptrUnit;

UnitTypeShort _unitType;

DAT_TribesState::instance.tribes[tribeID].rallyPointCount = 0;

_ptrUnit = &DAT_UnitsState::instance.units[1];

do {

if (_ptrUnit->logicalState != OpenSHC::Map::Units::ULS_INVISIBLE) {

_areInDifferentTeamsUnk = MACRO_CALL_MEMBER(OpenSHC::Game::GameStateStructures_Func::getTeamsDifferent,
DAT_GameState::ptr)(DAT_TribesState::instance.tribes[tribeID].owner, (int)((int)(_ptrUnit->owner)));

if (_areInDifferentTeamsUnk == FALSE) {

_unitType = _ptrUnit->unitType;

if ((((_unitType == OpenSHC::Map::Units::UT_S_CATAPULT)
|| (_unitType == OpenSHC::Map::Units::UT_S_TREBUCHET))
|| (_unitType == OpenSHC::Map::Units::UT_S_FBALLISTA))
&& (_ptrUnit->unknownSiegeTentRelated02 == 3)) {

MACRO_CALL_MEMBER(
OpenSHC::Map::Navigation::PathFindingState_Func::computeNextRallyPointDestination,
DAT_PathFindingState::ptr)(-1, (int)((int)(_ptrUnit->x)), (int)((int)(_ptrUnit->y)));

DAT_TribesState::instance.tribes[tribeID]
.rallyPointArray[DAT_TribesState::instance.tribes[tribeID].rallyPointCount][0]
= (short)DAT_PathFindingState::instance.ALG_ResultX;

DAT_TribesState::instance.tribes[tribeID]
.rallyPointArray[DAT_TribesState::instance.tribes[tribeID].rallyPointCount][1]
= (short)DAT_PathFindingState::instance.ALG_ResultY;

psVar1 = &DAT_TribesState::instance.tribes[tribeID].rallyPointCount;

*psVar1 = *psVar1 + 1;

if (8 < DAT_TribesState::instance.tribes[tribeID].rallyPointCount)
break;
}
}
}

_ptrUnit = _ptrUnit + 0x248;

} while ((int)_ptrUnit < 0x165141a);

if (DAT_TribesState::instance.tribes[tribeID].currentRallyPointIndex < 0) {

DAT_TribesState::instance.tribes[tribeID].currentRallyPointIndex = 0;
}

if (DAT_TribesState::instance.tribes[tribeID].rallyPointCount
<= DAT_TribesState::instance.tribes[tribeID].currentRallyPointIndex) {

DAT_TribesState::instance.tribes[tribeID].currentRallyPointIndex = 0;
}

return;
}

}
}
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 iVar1 = (int)DAT_UnitsState::instance.units[unitID].owner;
if (DAT_GameState::instance.playerDataArray[iVar1].aiType != AITA_NULL) {
DAT_UnitsState::instance.units[unitID].aiUnitBehaviourType = (short)aiUnitBehaviourType;
iVar1 = MACRO_CALL_MEMBER(AICState_Func::addUnitToSmallestBehaviourTypeTribe, this)(
iVar1, unitID, aiUnitBehaviourType);
if (iVar1 != 0) {
MACRO_CALL_MEMBER(Map::Units::TribesState_Func::addUnitToTribe, DAT_TribesState::ptr)(unitID, iVar1);
}
}
}
}
}
91 changes: 91 additions & 0 deletions src/OpenSHC/AI/AICState/addUnitToSmallestBehaviourTypeTribe.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
#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 param_2, undefined4 aiUnitBehaviourType)
{
int _playerID = (int)playerID;
int AVar1 = DAT_GameState::instance.playerDataArray[_playerID].aiType;
if (AVar1 == AITA_NULL) {
return 0;
}
int _tribeTypeOffset
= DAT_SkirmishDefinedData::instance.AIUnitBehaviourTypeMapping[(int)aiUnitBehaviourType + -10];
int _smallestTribe = 0;
int _smallestTribeOffset = 0;
short _smallestTribeSize = 1000;
dword _groupsCount;

if (_tribeTypeOffset == 0xf) {
_groupsCount = this->aics[AVar1 - 1].AttUnitPatrolGroupsCount;
} else if (_tribeTypeOffset == 0xba) {
_groupsCount = this->aics[AVar1 - 1].AttUnitBackupGroupsCount;
} else if (_tribeTypeOffset == 0xbe) {
_groupsCount = this->aics[AVar1 - 1].AttUnitSiegeDefGroupsCount;
} else if (_tribeTypeOffset == 0xc0) {
_groupsCount = this->aics[AVar1 - 1].AttMainGroupsCount;
} else {
_groupsCount = 1;
}

int _selectedTribe;
int _selectedSlot;
if ((int)_groupsCount < 1 || _groupsCount == 1) {
int _tribeID_groupsCount1
= (int)DAT_GameState::instance.playerDataArray[_playerID].aiTribeIDs[_tribeTypeOffset];
if ((_tribeID_groupsCount1 != 0)
&& (DAT_TribesState::instance.tribes[_tribeID_groupsCount1].uid
== DAT_GameState::instance.playerDataArray[_playerID].aiTribeUIDs[_tribeTypeOffset])) {
return _tribeID_groupsCount1;
}
_selectedTribe = MACRO_CALL_MEMBER(
Map::Units::TribesState_Func::createTribeForPlayer, DAT_TribesState::ptr)(_playerID);
_selectedSlot = _tribeTypeOffset;
} else {
int _maxOffset = _groupsCount + _tribeTypeOffset;
_selectedTribe = 0;
_selectedSlot = 0;
short* _pTribeIDs = DAT_GameState::instance.playerDataArray[_playerID].aiTribeIDs + _tribeTypeOffset;
if (_tribeTypeOffset < _maxOffset) {
do {
int _tribeID_2 = (int)*_pTribeIDs;
if ((_tribeID_2 == 0)
|| (DAT_TribesState::instance.tribes[_tribeID_2].uid
!= DAT_GameState::instance.playerDataArray[_playerID].aiTribeUIDs[_tribeTypeOffset])) {
_selectedTribe = MACRO_CALL_MEMBER(
Map::Units::TribesState_Func::createTribeForPlayer, DAT_TribesState::ptr)(_playerID);
_selectedSlot = _tribeTypeOffset;
break;
}
short _tribeSize = DAT_TribesState::instance.tribes[_tribeID_2].size;
if (_tribeSize < _smallestTribeSize) {
_smallestTribeOffset = _tribeTypeOffset;
_smallestTribe = _tribeID_2;
_smallestTribeSize = _tribeSize;
}
_pTribeIDs = _pTribeIDs + 1;
_tribeTypeOffset = _tribeTypeOffset + 1;
_selectedTribe = _smallestTribe;
_selectedSlot = _smallestTribeOffset;
} while (_tribeTypeOffset < _maxOffset);
}
}
if (0 < _selectedTribe) {
DAT_GameState::instance.playerDataArray[_playerID].aiTribeIDs[_selectedSlot] = (short)_selectedTribe;
DAT_GameState::instance.playerDataArray[_playerID].aiTribeUIDs[_selectedSlot]
= DAT_TribesState::instance.tribes[_selectedTribe].uid;
return _selectedTribe;
}
return 0;
}
}
}
28 changes: 28 additions & 0 deletions src/OpenSHC/AI/AICState/addUnitToSmallestPatrolTribe.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#include "../AICState.func.hpp"

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

#include "OpenSHC/Globals/DAT_AICState.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 iVar1 = (int)DAT_UnitsState::instance.units[unitID].owner;
int _aiType = DAT_GameState::instance.playerDataArray[iVar1].aiType;
if (_aiType != AITA_NULL) {
DAT_UnitsState::instance.units[unitID].aiUnitBehaviourType = 4;
iVar1 = MACRO_CALL_MEMBER(AI::AICState_Func::getSmallestPatrolTribe, DAT_AICState::ptr)(
iVar1, (int)this->aics[_aiType - 1].OuterPatrolGroupsCount);
MACRO_CALL_MEMBER(Map::Units::TribesState_Func::addUnitToTribe, DAT_TribesState::ptr)(unitID, iVar1);
}
}
}
}
Loading