Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
5 changes: 4 additions & 1 deletion cmake/compiler-flags-gl.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,7 @@ 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/AIVState/executeDefaultCastleAIV.cpp
src/OpenSHC/AI/AIVState/findAppropriateGridLocationForBuilding.cpp
14 changes: 14 additions & 0 deletions src/OpenSHC/AI/AIVState/Constructor_AIVState.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#include "../AIVState.func.hpp"

namespace OpenSHC {
namespace AI {

// FUNCTION: STRONGHOLDCRUSADER 0x004F13E0
AIVState* AIVState::Constructor_AIVState()
{
MACRO_CALL_MEMBER(AIVState_Func::wipeAIVsAndHeatMaps, this)();
return this;
}

}
}
321 changes: 321 additions & 0 deletions src/OpenSHC/AI/AIVState/aiPlaceAIVBuilding.cpp

Large diffs are not rendered by default.

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

#include "OpenSHC/Game/GameStateStructures.func.hpp"
#include "OpenSHC/Map/TileMapState.func.hpp"

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

namespace OpenSHC {
namespace AI {

// FUNCTION: STRONGHOLDCRUSADER 0x004EFC30
void AIVState::aiPlaceAdditionalOxtether(int playerID)
{
if (!MACRO_CALL_MEMBER(Game::GameStateStructures_Func::checkRequiredResourcesForBuildingOrPlanToBuy,
DAT_GameState::ptr)(Commands::M_MAPPER_OXENBASE, playerID, FALSE)
|| DAT_BuildingsState::instance.unknownCountdown01 < 20) {
return;
}

int const quarryID = DAT_GameState::instance.playerDataArray[playerID].highestLoadedQuarryUnk;
MACRO_CALL_MEMBER(AIVState_Func::findSuitableGridLocationFittingCriteria, this)(
(short)DAT_BuildingsState::instance.buildings[quarryID].x / 5
+ DAT_AIVDefinedData::instance
.OffsetsForFiveByFiveAreaSpotCheck[this->mapExtraInfo.algBuildingPlacementNudge % 9]
.x,
(short)DAT_BuildingsState::instance.buildings[quarryID].y / 5
+ DAT_AIVDefinedData::instance
.OffsetsForFiveByFiveAreaSpotCheck[this->mapExtraInfo.algBuildingPlacementNudge % 9]
.y);
if (this->buildingApproriateGridXPosition == -1) {
return;
}

++this->heatMaps[this->buildingApproriateGridXPosition][this->buildingAppropriateGridYPosition].structureCount;
MACRO_CALL_MEMBER(Map::TileMapState_Func::placeBuilding, DAT_TileMapState::ptr)(playerID,
this->buildingApproriateGridXPosition * 5, this->buildingAppropriateGridYPosition * 5,
Commands::M_MAPPER_OXENBASE,
MACRO_CALL_MEMBER(Map::TileMapState_Func::getBuildingSizeForCommandBuildingType, DAT_TileMapState::ptr)(
Commands::M_MAPPER_OXENBASE),
// rotation 15 is a magic value: the building ends up with rotation 0
// unless DAT_TileMapState::skipPlacementCheck is set
15);

// link the new ox tether to the first free slot of the quarry
int const oxTetherID = DAT_TileMapState::instance.placedBuildingID;
for (int tetherIndex = 0; tetherIndex < 3; ++tetherIndex) {
if (DAT_BuildingsState::instance.buildings[quarryID].quarryLinkedOxTethers[tetherIndex] == 0) {
DAT_BuildingsState::instance.buildings[quarryID].quarryLinkedOxTethers[tetherIndex] = (short)oxTetherID;
break;
}
}
DAT_BuildingsState::instance.buildings[oxTetherID].oxtetherLinkedQuarryID = (short)quarryID;
}

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

#include "OpenSHC/Map/Entities/EntityState.func.hpp"
#include "OpenSHC/Map/TileMapState.func.hpp"
#include "OpenSHC/AI/AIVUnitType.hpp"

#include "OpenSHC/Globals/DAT_EntityState.hpp"
#include "OpenSHC/Globals/DAT_GameState.hpp"
#include "OpenSHC/Globals/DAT_TileMapState.hpp"
#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp"

namespace OpenSHC {
namespace AI {

// FUNCTION: STRONGHOLDCRUSADER 0x004ED300
void AIVState::aiPlaceBrazier(int playerID)
{
if (DAT_GameState::instance.playerDataArray[playerID].aivUnitLocationSlotLocationCount[AIVUT_BRAZIER] <= 0) {
return;
}
for (int i = 0; i < 10; ++i) {
int const tile = DAT_GameState::instance.playerDataArray[playerID].aivUnitLocationSlots[AIVUT_BRAZIER][i];
if (tile <= 0) {
continue;
}
int const entityID = DAT_TileMapState::instance.EntityLayer[tile];
if (entityID != 0
&& DAT_EntityState::instance.entityArray[entityID].entityType == Map::Entities::ET_BRAZIER) {
continue;
}
uint const height
= MACRO_CALL_MEMBER(Map::TileMapState_Func::getTotalHeightAtTile, DAT_TileMapState::ptr)(tile);
if ((int)height <= 0) {
continue;
}
MACRO_CALL_MEMBER(Map::Entities::EntityState_Func::spawnProjectileEntity, DAT_EntityState::ptr)(0, playerID,
playerID,
(tile
- DAT_ViewportRenderState::instance
.translationMatrix[DAT_ViewportRenderState::instance.tileTranslationMatrix_YComponent[tile]]
.addXgetTile)
* 8,
DAT_ViewportRenderState::instance.tileTranslationMatrix_YComponent[tile] * 8, height, 0, 0, 0,
Map::Entities::ET_BRAZIER, 0);
}
}

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

#include "OpenSHC/Game/GameStateStructures.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 0x004EFA60
BOOLEnum AIVState::aiPlaceFarm(int playerID, MappersEnum buildingType)
{
// despite its declared type, buildingType holds a BuildingType
if (buildingType <= 0) {
return FALSE;
}
if (!MACRO_CALL_MEMBER(
Game::GameStateStructures_Func::checkRequiredResourcesForBuildingOrPlanToBuy, DAT_GameState::ptr)(
MACRO_CALL_MEMBER(Map::Buildings::BuildingsState_Func::convertBuildingTypeToCommandBuildingType,
DAT_BuildingsState::ptr)((Map::Buildings::BuildingType)buildingType),
playerID, FALSE)) {
return FALSE;
}
return MACRO_CALL_MEMBER(AIVState_Func::findSuitableFarmLocationAndPlaceFarm, this)(playerID, buildingType)
!= FALSE;
}

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

#include "OpenSHC/Game/GameStateStructures.func.hpp"
#include "OpenSHC/Map/TileMapState.func.hpp"

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

namespace OpenSHC {
namespace AI {

// FUNCTION: STRONGHOLDCRUSADER 0x004EFE30
void AIVState::aiPlaceIronMine(int playerID)
{
if (!MACRO_CALL_MEMBER(Game::GameStateStructures_Func::checkRequiredResourcesForBuildingOrPlanToBuy,
DAT_GameState::ptr)(Commands::M_MAPPER_IRON_MINE, playerID, FALSE)
|| DAT_BuildingsState::instance.unknownCountdown01 < 20) {
return;
}
MACRO_CALL_MEMBER(AIVState_Func::findAppropriateGridLocationForResourceTypeBuilding, this)(
playerID, AIGCRT_IRON);
if (this->buildingApproriateGridXPosition == -1) {
return;
}
++this->heatMaps[this->buildingApproriateGridXPosition][this->buildingAppropriateGridYPosition].structureCount;
MACRO_CALL_MEMBER(Map::TileMapState_Func::placeBuilding, DAT_TileMapState::ptr)(playerID,
this->buildingApproriateGridXPosition * 5, this->buildingAppropriateGridYPosition * 5,
Commands::M_MAPPER_IRON_MINE,
MACRO_CALL_MEMBER(Map::TileMapState_Func::getBuildingSizeForCommandBuildingType, DAT_TileMapState::ptr)(
Commands::M_MAPPER_IRON_MINE),
// rotation 15 is a magic value: the building ends up with rotation 0
// unless DAT_TileMapState::skipPlacementCheck is set
15);
Comment thread
TheRedDaemon marked this conversation as resolved.
}

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

#include "OpenSHC/Game/GameStateStructures.func.hpp"
#include "OpenSHC/Map/TileMapState.func.hpp"

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

namespace OpenSHC {
namespace AI {

// FUNCTION: STRONGHOLDCRUSADER 0x004EFD90
void AIVState::aiPlacePitchrig(int playerID)
{
if (!MACRO_CALL_MEMBER(Game::GameStateStructures_Func::checkRequiredResourcesForBuildingOrPlanToBuy,
DAT_GameState::ptr)(Commands::M_MAPPER_PITCH_WORKINGS, playerID, FALSE)
|| DAT_BuildingsState::instance.unknownCountdown01 < 20) {
return;
}
MACRO_CALL_MEMBER(AIVState_Func::findAppropriateGridLocationForResourceTypeBuilding, this)(
playerID, AIGCRT_OIL);
if (this->buildingApproriateGridXPosition == -1) {
return;
}
++this->heatMaps[this->buildingApproriateGridXPosition][this->buildingAppropriateGridYPosition].structureCount;
MACRO_CALL_MEMBER(Map::TileMapState_Func::placeBuilding, DAT_TileMapState::ptr)(playerID,
this->buildingApproriateGridXPosition * 5, this->buildingAppropriateGridYPosition * 5,
Commands::M_MAPPER_PITCH_WORKINGS,
MACRO_CALL_MEMBER(Map::TileMapState_Func::getBuildingSizeForCommandBuildingType, DAT_TileMapState::ptr)(
Commands::M_MAPPER_PITCH_WORKINGS),
// rotation 15 is a magic value: the building ends up with rotation 0
// unless DAT_TileMapState::skipPlacementCheck is set
15);
}

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

#include "OpenSHC/Game/GameStateStructures.func.hpp"
#include "OpenSHC/Map/TileMapState.func.hpp"

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

namespace OpenSHC {
namespace AI {

// FUNCTION: STRONGHOLDCRUSADER 0x004EFED0
void AIVState::aiPlaceQuarryAndOxtether(int playerID)
{
if (!MACRO_CALL_MEMBER(Game::GameStateStructures_Func::checkRequiredResourcesForBuildingOrPlanToBuy,
DAT_GameState::ptr)(Commands::M_MAPPER_QUARRY, playerID, FALSE)
|| DAT_BuildingsState::instance.unknownCountdown01 < 20) {
return;
}
MACRO_CALL_MEMBER(AIVState_Func::findAppropriateGridLocationForResourceTypeBuilding, this)(
playerID, AIGCRT_BOULDER);
if (this->buildingApproriateGridXPosition == -1) {
return;
}

++this->heatMaps[this->buildingApproriateGridXPosition][this->buildingAppropriateGridYPosition].structureCount;
int const quarryXOffset
= DAT_AIVDefinedData::instance
.OffsetsForClockwiseThreeByThreeAreaCheck[this->mapExtraInfo.algBuildingPlacementNudge % 9]
.x;
int const quarryYOffset
= DAT_AIVDefinedData::instance
.OffsetsForClockwiseThreeByThreeAreaCheck[this->mapExtraInfo.algBuildingPlacementNudge % 9]
.y;
MACRO_CALL_MEMBER(Map::TileMapState_Func::placeBuilding, DAT_TileMapState::ptr)(playerID,
quarryXOffset + this->buildingApproriateGridXPosition * 5,
quarryYOffset + this->buildingAppropriateGridYPosition * 5, Commands::M_MAPPER_QUARRY,
MACRO_CALL_MEMBER(Map::TileMapState_Func::getBuildingSizeForCommandBuildingType, DAT_TileMapState::ptr)(
Commands::M_MAPPER_QUARRY),
// rotation 15 is a magic value: the building ends up with rotation 0
// unless DAT_TileMapState::skipPlacementCheck is set
15);
if (DAT_TileMapState::instance.buildingPlacementFail) {
return;
}
int const quarryID = DAT_TileMapState::instance.placedBuildingID;
MACRO_CALL_MEMBER(AIVState_Func::findSuitableGridLocationFittingCriteria, this)(
this->buildingApproriateGridXPosition, this->buildingAppropriateGridYPosition);
if (this->buildingApproriateGridXPosition == -1) {
return;
}

// place an ox tether on the first free side and link it to the quarry
for (int side = 0; side < 4; ++side) {
int const xOffset = DAT_AIVDefinedData::instance.OffsetsForSpotCheckThreeByThreeAreaOnTheSide[side].x;
int const yOffset = DAT_AIVDefinedData::instance.OffsetsForSpotCheckThreeByThreeAreaOnTheSide[side].y;
MACRO_CALL_MEMBER(Map::TileMapState_Func::placeBuilding, DAT_TileMapState::ptr)(playerID,
xOffset + this->buildingApproriateGridXPosition * 5,
yOffset + this->buildingAppropriateGridYPosition * 5, Commands::M_MAPPER_OXENBASE,
MACRO_CALL_MEMBER(Map::TileMapState_Func::getBuildingSizeForCommandBuildingType, DAT_TileMapState::ptr)(
Commands::M_MAPPER_OXENBASE),
// rotation 15 is a magic value: the building ends up with rotation 0
// unless DAT_TileMapState::skipPlacementCheck is set
15);
if (!DAT_TileMapState::instance.buildingPlacementFail) {
int const oxTetherID = DAT_TileMapState::instance.placedBuildingID;
DAT_BuildingsState::instance.buildings[quarryID].quarryLinkedOxTethers[0] = (short)oxTetherID;
DAT_BuildingsState::instance.buildings[oxTetherID].oxtetherLinkedQuarryID = (short)quarryID;
return;
}
}
}

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

#include "OpenSHC/IO/LowLevelMemory.func.hpp"

#include "OpenSHC/Globals/DAT_LowLevelMemory.hpp"

namespace OpenSHC {
namespace AI {

// FUNCTION: STRONGHOLDCRUSADER 0x004EDC90
void AIVState::clearTheHeatmaps()
{
MACRO_CALL_MEMBER(IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)(
sizeof(this->heatMaps), 0, this->heatMaps);
}

}
}
Loading
Loading