diff --git a/src/OpenSHC/Map/LogicHelpers/Logic1.hpp b/src/OpenSHC/Map/LogicHelpers/Logic1.hpp index b1b0e4dfe3..6f621f3bfc 100644 --- a/src/OpenSHC/Map/LogicHelpers/Logic1.hpp +++ b/src/OpenSHC/Map/LogicHelpers/Logic1.hpp @@ -20,6 +20,7 @@ namespace Map { L_PLAIN2_AND_PITCH = 8, // 0x00000008 L_BORDER = 16, // 0x00000010 L_BORDER_EDGE = 32, // 0x00000020 + L_UNNAMED_0x40 = 64, // 0x00000040 L_ROCKY = 128, // 0x00000080 L_WALL_OR_GATEHOUSE = 256, // 0x00000100 L_CRENEL = 512, // 0x00000200 diff --git a/src/OpenSHC/Map/Moat.hpp b/src/OpenSHC/Map/Moat.hpp index a676966a90..1d35bbf0ec 100644 --- a/src/OpenSHC/Map/Moat.hpp +++ b/src/OpenSHC/Map/Moat.hpp @@ -15,10 +15,9 @@ namespace Map { // SIZE: 0x00000010 typedef struct Moat { - ushort tile; // 0x00000000 length: 2 - undefined1 padding_0x2[2]; // 0x00000002 length: 2 - undefined2 x; // 0x00000004 length: 2 - undefined2 y; // 0x00000006 length: 2 + int tile; // 0x00000000 length: 4 + short x; // 0x00000004 length: 2 + short y; // 0x00000006 length: 2 short zeroOrTwo; // 0x00000008 length: 2 undefined1 padding_0xa[2]; // 0x0000000A length: 2 char owner; // 0x0000000C length: 1 diff --git a/src/OpenSHC/Map/TerrainDefinedData.hpp b/src/OpenSHC/Map/TerrainDefinedData.hpp index 42ed493f3d..44403d1cdd 100644 --- a/src/OpenSHC/Map/TerrainDefinedData.hpp +++ b/src/OpenSHC/Map/TerrainDefinedData.hpp @@ -43,9 +43,8 @@ namespace Map { XYPair StockpilePathableOffsets[9]; // 0x000001DC length: 72 undefined1 padding_0x224[64]; // 0x00000224 length: 64 XYPair field130_0x264[3][12]; // 0x00000264 length: 288 - Point8IntXY unkXYOffsets_0x384[8]; // 0x00000384 length: 64 - Point8IntXY field132_0x3c4[8]; // 0x000003C4 length: 64 - undefined1 padding_0x404[64]; // 0x00000404 length: 64 + Point8IntXY keepOutbuildingOffsets_0x384[3][4]; // 0x00000384 length: 96 + Point8IntXY keepOutbuildingOffsets_0x3e4[3][4]; // 0x000003E4 length: 96 XYPair field197_0x444[24]; // 0x00000444 length: 192 undefined1 padding_0x504[8]; // 0x00000504 length: 8 XYPair field206_0x50c; // 0x0000050C length: 8 diff --git a/src/OpenSHC/Map/TileMapState.hpp b/src/OpenSHC/Map/TileMapState.hpp index 28aa939380..971be83327 100644 --- a/src/OpenSHC/Map/TileMapState.hpp +++ b/src/OpenSHC/Map/TileMapState.hpp @@ -76,11 +76,11 @@ namespace Map { uchar unitDeathHeatMap[80400]; // 0x00428370 length: 80400 uchar SEC_TileMap1104[80400]; // 0x0043BD80 length: 80400 uchar SEC_PathfindingCostTileMap1105[9][80400]; // 0x0044F790 length: 723600 - undefined4 someIndex; // 0x00500220 length: 4 - undefined4 someLimit; // 0x00500224 length: 4 - undefined4 someYLike; // 0x00500228 length: 4 - undefined4 someYLikeLimit; // 0x0050022C length: 4 - byte mapping40x40[40][40]; // 0x00500230 length: 1600 + int someIndex; // 0x00500220 length: 4 + int someLimit; // 0x00500224 length: 4 + int someYLike; // 0x00500228 length: 4 + int someYLikeLimit; // 0x0050022C length: 4 + char mapping40x40[40][40]; // 0x00500230 length: 1600 Moat moats[16000]; // 0x00500870 length: 256000 int currentMoatCount; // 0x0053F070 length: 4 undefined4 moatTileCount; // 0x0053F074 length: 4 @@ -88,19 +88,19 @@ namespace Map { undefined4 ALG_MoatYResult; // 0x0053F07C length: 4 int someMoatTile; // 0x0053F080 length: 4 PitchDitch pitchDitches[4000]; // 0x0053F084 length: 80000 - undefined4 maxPitchDitchCount; // 0x00552904 length: 4 + int maxPitchDitchCount; // 0x00552904 length: 4 undefined1 padding_0x552908[4]; // 0x00552908 length: 4 short specialAreasArray[8]; // 0x0055290C length: 16 - undefined4 temporaryTerrainTypeIndex; // 0x0055291C length: 4 - undefined4 SEC_Section1052; // 0x00552920 length: 4 - undefined4 SEC_Section1053; // 0x00552924 length: 4 - undefined4 SEC_Section1054; // 0x00552928 length: 4 + int temporaryTerrainTypeIndex; // 0x0055291C length: 4 + int SEC_Section1052; // 0x00552920 length: 4 + int SEC_Section1053; // 0x00552924 length: 4 + int SEC_Section1054; // 0x00552928 length: 4 int temporaryTerrainTypeArray[1000]; // 0x0055292C length: 4000 int temporaryTerrainTypeBinaryArray[1000]; // 0x005538CC length: 4000 undefined4 forceUpdateLogicalAndMiscDisplayLayers; // 0x0055486C length: 4 - undefined4 forceUpdateTextureTilemap; // 0x00554870 length: 4 - undefined4 forceUpdateGFXLayers; // 0x00554874 length: 4 - undefined4 forceUpdateMacroLayerFlag; // 0x00554878 length: 4 + int forceUpdateTextureTilemap; // 0x00554870 length: 4 + int forceUpdateGFXLayers; // 0x00554874 length: 4 + int forceUpdateMacroLayerFlag; // 0x00554878 length: 4 undefined4 field68_0x55487c; // 0x0055487C length: 4 undefined1 padding_0x554880[8]; // 0x00554880 length: 8 undefined4 placedBuildingID; // 0x00554888 length: 4 @@ -121,7 +121,7 @@ namespace Map { undefined4 refreshRelatedOne; // 0x005548C4 length: 4 undefined4 disableElevationRendering; // 0x005548C8 length: 4 undefined4 flatViewToggleValue1; // 0x005548CC length: 4 - undefined1 padding_0x5548d0[4]; // 0x005548D0 length: 4 + undefined4 field95_0x5548d0; // 0x005548D0 length: 4 undefined4 flatViewToggleValue2; // 0x005548D4 length: 4 undefined4 refreshRelatedTwo; // 0x005548D8 length: 4 undefined4 savedEditorActiveBrush; // 0x005548DC length: 4 @@ -156,8 +156,8 @@ namespace Map { undefined4 buildingSpriteID2; // 0x00554950 length: 4 undefined4 cursorTargetID; // 0x00554954 length: 4 undefined4 buildingHeightLimit; // 0x00554958 length: 4 - undefined4 buildingMinHeight; // 0x0055495C length: 4 - undefined4 buildingMaxHeight; // 0x00554960 length: 4 + int buildingMinHeight; // 0x0055495C length: 4 + int buildingMaxHeight; // 0x00554960 length: 4 undefined4 buildingMaxHeightDifference; // 0x00554964 length: 4 undefined4 buildingPlacementProperty_3; // 0x00554968 length: 4 undefined4 buildingPlacementProperty_4; // 0x0055496C length: 4 diff --git a/src/OpenSHC/Map/TileMapState/Constructor_TileMapState.cpp b/src/OpenSHC/Map/TileMapState/Constructor_TileMapState.cpp new file mode 100644 index 0000000000..64cb01b0bd --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/Constructor_TileMapState.cpp @@ -0,0 +1,66 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Commands/MappersEnum.hpp" +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +#include "OpenSHC/Globals/DAT_GameCore.hpp" +#include "OpenSHC/Globals/DAT_GameState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Commands::MappersEnum; + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x00515F40 + TileMapState* TileMapState::Constructor_TileMapState() + { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::setupMovementDirectionTranslationMatrix, this)(); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::setupBuildingSizeIndexMapping, this)(); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::setupTileMapSections, this)(); + this->editorActiveBrush = 7; + this->refreshCertainTileMap = 2; + this->counter1 = 0; + this->mapperMax = FALSE; + this->editorSnapToMode = 0; + this->editorAffectType = 0; + this->unknownZero_0x554900 = 0; + this->currentMapperCommand = OpenSHC::Commands::M_MAPPER_NULL; + this->refreshRelatedOne = 1; + this->disableElevationRendering = 0; + this->refreshRelatedTwo = 0; + this->forceUpdateLogicalAndMiscDisplayLayers = 1; + this->forceUpdateTextureTilemap = 1; + this->forceUpdateGFXLayers = 1; + this->refreshCertainTileMap_old = 4; + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::setChangedLayerToThreeAndMapping0x40x40, this)(); + this->moatTileCount = 0; + this->skipPlacementCheck = 0; + this->gateOrientationVariant = 0x50; + this->lastTime = timeGetTime(); + this->rockOrientation = 0; + this->editorRockType = 0; + this->cursorAnimationTime = timeGetTime(); + this->cursorOverlayAnimationFrame = 1; + this->temporaryTerrainTypeIndex = 0; + this->skipPlacementFailChecks = 0; + DAT_GameCore::instance.isTimeHalted = FALSE; + DAT_GameState::instance.mapAndTime.skirmishFogOfWar = 0; + this->ptr_LogicLayer = this->LogicLayer; + this->ptr_ChangedLayer = this->ChangedLayer; + this->ptr_TerrainTypeTileMap = this->Logic2Layer; + this->ptr_TerrainHeightTileMap = this->HeightLayer; + this->ptr_PathConnectionLayer = this->PathConnectionLayer; + this->ptr_OccupancyLayer = this->OccupancyLayer; + this->ptr_DamageLayer = this->DamageLayer; + this->ptr_MiscDisplayLayer = this->MiscDisplayLayer; + this->ptr_MovementDirectionTranslationMatrix = this; + this->ptr_SpecialAreasArray = this->specialAreasArray; + this->ptr_AIZoneLayer = this->AIZoneLayer; + this->currentMoatCount = 16000; + this->maxPitchDitchCount = 4000; + return this; + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/NeighbourFlagsAsm.hpp b/src/OpenSHC/Map/TileMapState/NeighbourFlagsAsm.hpp new file mode 100644 index 0000000000..4ad078a7f7 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/NeighbourFlagsAsm.hpp @@ -0,0 +1,354 @@ +/** + HAND WRITTEN - not generated. + + path: 'OpenSHC/Map/TileMapState/NeighbourFlagsAsm.hpp' + + The original gathers the neighbours of DAT_SomeTile into bitFlag with handwritten assembly, and that + assembly is a MACRO: the identical instruction stream appears verbatim inside + setBitFlagBasedOnWallTowerGatehouseOrKeep (0x004FF870, once), updateGFXLayers (0x004FC9E0, eleven + times), updateMacroLayerRelated (0x004FDB00, eleven times) and updateGfxLayer (0x00509180, nineteen + times) - never as a call. It is recognisable by "mov edx, 0" (no compiler materialises zero that + way), by advancing the row pointer with repeated "add esi, ecx" instead of one scaled lea, and, in + the TERRAIN variants, by loading a dword at a one-byte offset and masking it down to the low byte. + + Five shapes occur, selected by which layer pointer is read and how many neighbours are gathered: + + LOGIC - ptr_LogicLayer, 4-byte elements: "shl eax, 2", "add esi, ecx" x4, [esi +/- 4] + MISC - ptr_MiscDisplayLayer, 2-byte elements: "shl eax, 1", "add esi, ecx" x2, [esi +/- 2] + TERRAIN - ptr_TerrainTypeTileMap, 1-byte elements: no shift, "add esi, ecx" x1, [esi +/- 1] + _4 - east, west, north and south only + _8 - also north-west, north-east, south-west and south-east + + bitFlag bits: 0x02 west, 0x20 east, 0x80 north, 0x08 south, + 0x01 north-west, 0x40 north-east, 0x04 south-west, 0x10 south-east. + + Every expansion clobbers eax, ebx, ecx, edx, esi and edi and leaves the result in this->bitFlag. + + ID must be unique within the enclosing function; it exists only to keep the asm labels of two + expansions apart. MASK must be a numeric literal or a preprocessor constant: MASM has no "|" + operator, so an enum OR expression cannot be used as an asm operand. + + The original reaches the fields through the global instance's absolute address; we go through "this" + because MSVC inline asm cannot name DAT_TileMapState::instance ("::" is not parseable in an asm + operand). That costs the "mov eax, this" instructions and nothing else. +*/ + +#pragma once + +#include "OpenSHC/Map/TileMapState.hpp" + +// clang-format off + +#define MACRO_NEIGHBOUR_FLAGS_LOGIC_4(ID, MASK) \ + __asm mov eax, this \ + __asm mov edi, dword ptr [eax]TileMapState.ptr_MovementDirectionTranslationMatrix \ + __asm mov esi, dword ptr [eax]TileMapState.ptr_LogicLayer \ + __asm mov eax, dword ptr [eax]TileMapState.DAT_SomeTile \ + __asm shl eax, 0x2 \ + __asm add esi, eax \ + __asm push esi \ + __asm mov eax, this \ + __asm mov eax, dword ptr [eax]TileMapState.DAT_SomeY \ + __asm shl eax, 0x5 \ + __asm add edi, eax \ + __asm mov edx, 0x0 \ + __asm mov eax, dword ptr [esi + 0x4] \ + __asm mov ebx, dword ptr [esi - 0x4] \ + __asm and eax, MASK \ + __asm jz east_done_##ID \ + __asm or edx, 0x20 \ + __asm east_done_##ID: \ + __asm and ebx, MASK \ + __asm jz west_done_##ID \ + __asm or edx, 0x2 \ + __asm west_done_##ID: \ + __asm mov ecx, dword ptr [edi] \ + __asm add esi, ecx \ + __asm add esi, ecx \ + __asm add esi, ecx \ + __asm add esi, ecx \ + __asm mov eax, dword ptr [esi] \ + __asm and eax, MASK \ + __asm jz north_done_##ID \ + __asm or edx, 0x80 \ + __asm north_done_##ID: \ + __asm mov ecx, dword ptr [edi + 0x10] \ + __asm pop esi \ + __asm add esi, ecx \ + __asm add esi, ecx \ + __asm add esi, ecx \ + __asm add esi, ecx \ + __asm mov eax, dword ptr [esi] \ + __asm and eax, MASK \ + __asm jz south_done_##ID \ + __asm or edx, 0x8 \ + __asm south_done_##ID: \ + __asm mov eax, this \ + __asm mov byte ptr [eax]TileMapState.bitFlag, dl + +#define MACRO_NEIGHBOUR_FLAGS_LOGIC_8(ID, MASK) \ + __asm mov eax, this \ + __asm mov edi, dword ptr [eax]TileMapState.ptr_MovementDirectionTranslationMatrix \ + __asm mov esi, dword ptr [eax]TileMapState.ptr_LogicLayer \ + __asm mov eax, dword ptr [eax]TileMapState.DAT_SomeTile \ + __asm shl eax, 0x2 \ + __asm add esi, eax \ + __asm push esi \ + __asm mov eax, this \ + __asm mov eax, dword ptr [eax]TileMapState.DAT_SomeY \ + __asm shl eax, 0x5 \ + __asm add edi, eax \ + __asm mov edx, 0x0 \ + __asm mov eax, dword ptr [esi + 0x4] \ + __asm mov ebx, dword ptr [esi - 0x4] \ + __asm and eax, MASK \ + __asm jz east_done_##ID \ + __asm or edx, 0x20 \ + __asm east_done_##ID: \ + __asm and ebx, MASK \ + __asm jz west_done_##ID \ + __asm or edx, 0x2 \ + __asm west_done_##ID: \ + __asm mov ecx, dword ptr [edi] \ + __asm add esi, ecx \ + __asm add esi, ecx \ + __asm add esi, ecx \ + __asm add esi, ecx \ + __asm mov eax, dword ptr [esi - 0x4] \ + __asm mov ebx, dword ptr [esi + 0x4] \ + __asm mov ecx, dword ptr [esi] \ + __asm and eax, MASK \ + __asm jz north_west_done_##ID \ + __asm or edx, 0x1 \ + __asm north_west_done_##ID: \ + __asm and ebx, MASK \ + __asm jz north_east_done_##ID \ + __asm or edx, 0x40 \ + __asm north_east_done_##ID: \ + __asm and ecx, MASK \ + __asm jz north_done_##ID \ + __asm or edx, 0x80 \ + __asm north_done_##ID: \ + __asm mov ecx, dword ptr [edi + 0x10] \ + __asm pop esi \ + __asm add esi, ecx \ + __asm add esi, ecx \ + __asm add esi, ecx \ + __asm add esi, ecx \ + __asm mov eax, dword ptr [esi - 0x4] \ + __asm mov ebx, dword ptr [esi + 0x4] \ + __asm mov ecx, dword ptr [esi] \ + __asm and eax, MASK \ + __asm jz south_west_done_##ID \ + __asm or edx, 0x4 \ + __asm south_west_done_##ID: \ + __asm and ebx, MASK \ + __asm jz south_east_done_##ID \ + __asm or edx, 0x10 \ + __asm south_east_done_##ID: \ + __asm and ecx, MASK \ + __asm jz south_done_##ID \ + __asm or edx, 0x8 \ + __asm south_done_##ID: \ + __asm mov eax, this \ + __asm mov byte ptr [eax]TileMapState.bitFlag, dl + +#define MACRO_NEIGHBOUR_FLAGS_MISC_8(ID, MASK) \ + __asm mov eax, this \ + __asm mov edi, dword ptr [eax]TileMapState.ptr_MovementDirectionTranslationMatrix \ + __asm mov esi, dword ptr [eax]TileMapState.ptr_MiscDisplayLayer \ + __asm mov eax, dword ptr [eax]TileMapState.DAT_SomeTile \ + __asm shl eax, 0x1 \ + __asm add esi, eax \ + __asm push esi \ + __asm mov eax, this \ + __asm mov eax, dword ptr [eax]TileMapState.DAT_SomeY \ + __asm shl eax, 0x5 \ + __asm add edi, eax \ + __asm mov edx, 0x0 \ + __asm mov eax, dword ptr [esi + 0x2] \ + __asm mov ebx, dword ptr [esi - 0x2] \ + __asm and eax, MASK \ + __asm jz east_done_##ID \ + __asm or edx, 0x20 \ + __asm east_done_##ID: \ + __asm and ebx, MASK \ + __asm jz west_done_##ID \ + __asm or edx, 0x2 \ + __asm west_done_##ID: \ + __asm mov ecx, dword ptr [edi] \ + __asm add esi, ecx \ + __asm add esi, ecx \ + __asm mov eax, dword ptr [esi - 0x2] \ + __asm mov ebx, dword ptr [esi + 0x2] \ + __asm mov ecx, dword ptr [esi] \ + __asm and eax, MASK \ + __asm jz north_west_done_##ID \ + __asm or edx, 0x1 \ + __asm north_west_done_##ID: \ + __asm and ebx, MASK \ + __asm jz north_east_done_##ID \ + __asm or edx, 0x40 \ + __asm north_east_done_##ID: \ + __asm and ecx, MASK \ + __asm jz north_done_##ID \ + __asm or edx, 0x80 \ + __asm north_done_##ID: \ + __asm mov ecx, dword ptr [edi + 0x10] \ + __asm pop esi \ + __asm add esi, ecx \ + __asm add esi, ecx \ + __asm mov eax, dword ptr [esi - 0x2] \ + __asm mov ebx, dword ptr [esi + 0x2] \ + __asm mov ecx, dword ptr [esi] \ + __asm and eax, MASK \ + __asm jz south_west_done_##ID \ + __asm or edx, 0x4 \ + __asm south_west_done_##ID: \ + __asm and ebx, MASK \ + __asm jz south_east_done_##ID \ + __asm or edx, 0x10 \ + __asm south_east_done_##ID: \ + __asm and ecx, MASK \ + __asm jz south_done_##ID \ + __asm or edx, 0x8 \ + __asm south_done_##ID: \ + __asm mov eax, this \ + __asm mov byte ptr [eax]TileMapState.bitFlag, dl + +#define MACRO_NEIGHBOUR_FLAGS_TERRAIN_4(ID, MASK) \ + __asm mov eax, this \ + __asm mov edi, dword ptr [eax]TileMapState.ptr_MovementDirectionTranslationMatrix \ + __asm mov esi, dword ptr [eax]TileMapState.ptr_TerrainTypeTileMap \ + __asm mov eax, dword ptr [eax]TileMapState.DAT_SomeTile \ + __asm add esi, eax \ + __asm push esi \ + __asm mov eax, this \ + __asm mov eax, dword ptr [eax]TileMapState.DAT_SomeY \ + __asm shl eax, 0x5 \ + __asm add edi, eax \ + __asm mov edx, 0x0 \ + __asm mov eax, dword ptr [esi + 0x1] \ + __asm mov ebx, dword ptr [esi - 0x1] \ + __asm and eax, MASK \ + __asm jz east_done_##ID \ + __asm or edx, 0x20 \ + __asm east_done_##ID: \ + __asm and ebx, MASK \ + __asm jz west_done_##ID \ + __asm or edx, 0x2 \ + __asm west_done_##ID: \ + __asm mov ecx, dword ptr [edi] \ + __asm add esi, ecx \ + __asm mov eax, dword ptr [esi] \ + __asm and eax, MASK \ + __asm jz north_done_##ID \ + __asm or edx, 0x80 \ + __asm north_done_##ID: \ + __asm mov ecx, dword ptr [edi + 0x10] \ + __asm pop esi \ + __asm add esi, ecx \ + __asm mov eax, dword ptr [esi] \ + __asm and eax, MASK \ + __asm jz south_done_##ID \ + __asm or edx, 0x8 \ + __asm south_done_##ID: \ + __asm mov eax, this \ + __asm mov byte ptr [eax]TileMapState.bitFlag, dl + +#define MACRO_NEIGHBOUR_FLAGS_TERRAIN_8(ID, MASK) \ + __asm mov eax, this \ + __asm mov edi, dword ptr [eax]TileMapState.ptr_MovementDirectionTranslationMatrix \ + __asm mov esi, dword ptr [eax]TileMapState.ptr_TerrainTypeTileMap \ + __asm mov eax, dword ptr [eax]TileMapState.DAT_SomeTile \ + __asm add esi, eax \ + __asm push esi \ + __asm mov eax, this \ + __asm mov eax, dword ptr [eax]TileMapState.DAT_SomeY \ + __asm shl eax, 0x5 \ + __asm add edi, eax \ + __asm mov edx, 0x0 \ + __asm mov eax, dword ptr [esi + 0x1] \ + __asm mov ebx, dword ptr [esi - 0x1] \ + __asm and eax, MASK \ + __asm jz east_done_##ID \ + __asm or edx, 0x20 \ + __asm east_done_##ID: \ + __asm and ebx, MASK \ + __asm jz west_done_##ID \ + __asm or edx, 0x2 \ + __asm west_done_##ID: \ + __asm mov ecx, dword ptr [edi] \ + __asm add esi, ecx \ + __asm mov eax, dword ptr [esi - 0x1] \ + __asm mov ebx, dword ptr [esi + 0x1] \ + __asm mov ecx, dword ptr [esi] \ + __asm and eax, MASK \ + __asm jz north_west_done_##ID \ + __asm or edx, 0x1 \ + __asm north_west_done_##ID: \ + __asm and ebx, MASK \ + __asm jz north_east_done_##ID \ + __asm or edx, 0x40 \ + __asm north_east_done_##ID: \ + __asm and ecx, MASK \ + __asm jz north_done_##ID \ + __asm or edx, 0x80 \ + __asm north_done_##ID: \ + __asm mov ecx, dword ptr [edi + 0x10] \ + __asm pop esi \ + __asm add esi, ecx \ + __asm mov eax, dword ptr [esi - 0x1] \ + __asm mov ebx, dword ptr [esi + 0x1] \ + __asm mov ecx, dword ptr [esi] \ + __asm and eax, MASK \ + __asm jz south_west_done_##ID \ + __asm or edx, 0x4 \ + __asm south_west_done_##ID: \ + __asm and ebx, MASK \ + __asm jz south_east_done_##ID \ + __asm or edx, 0x10 \ + __asm south_east_done_##ID: \ + __asm and ecx, MASK \ + __asm jz south_done_##ID \ + __asm or edx, 0x8 \ + __asm south_done_##ID: \ + __asm mov eax, this \ + __asm mov byte ptr [eax]TileMapState.bitFlag, dl + +/* + A second handwritten macro: mark DAT_SomeTile and its eight neighbours as changed (2) in the + changed layer. It appears verbatim in createPlateau (0x00501F50), useLevelBrush (0x00502110) and + useTerrainHeightBrush (0x00502680), each time right after DAT_SomeTile and DAT_SomeY are stored. + Same tells as above: a bare push/pop of esi around the north row, and the fields read through the + global instance's absolute address. + + Clobbers eax, ecx, edx and esi. "this" is loaded once into ecx (which the original does not need) + so that no named operand is resolved while the pushed esi is on the stack. +*/ +#define MACRO_MARK_CHANGED_NEIGHBOURS() \ + __asm mov ecx, this \ + __asm mov esi, dword ptr [ecx]TileMapState.ptr_ChangedLayer \ + __asm mov eax, dword ptr [ecx]TileMapState.DAT_SomeTile \ + __asm add esi, eax \ + __asm push esi \ + __asm mov edx, dword ptr [ecx]TileMapState.ptr_MovementDirectionTranslationMatrix \ + __asm mov eax, dword ptr [ecx]TileMapState.DAT_SomeY \ + __asm shl eax, 0x5 \ + __asm add edx, eax \ + __asm mov byte ptr [esi + 0x1], 0x2 \ + __asm mov byte ptr [esi - 0x1], 0x2 \ + __asm mov byte ptr [esi], 0x2 \ + __asm mov ecx, dword ptr [edx] \ + __asm add esi, ecx \ + __asm mov byte ptr [esi - 0x1], 0x2 \ + __asm mov byte ptr [esi + 0x1], 0x2 \ + __asm mov byte ptr [esi], 0x2 \ + __asm mov ecx, dword ptr [edx + 0x10] \ + __asm pop esi \ + __asm add esi, ecx \ + __asm mov byte ptr [esi - 0x1], 0x2 \ + __asm mov byte ptr [esi + 0x1], 0x2 \ + __asm mov byte ptr [esi], 0x2 + +// clang-format on diff --git a/src/OpenSHC/Map/TileMapState/advanceMoatDigProgress.cpp b/src/OpenSHC/Map/TileMapState/advanceMoatDigProgress.cpp new file mode 100644 index 0000000000..1ae40bbeb7 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/advanceMoatDigProgress.cpp @@ -0,0 +1,48 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" +#include "OpenSHC/UI/MinimapViewState.func.hpp" + +#include "OpenSHC/Globals/DAT_MinimapViewState.hpp" +#include "OpenSHC/Globals/DAT_PathFindingState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_MOAT; + using OpenSHC::Map::LogicHelpers::L_MOAT_DUG_OR_PLANNED; + using OpenSHC::Map::LogicHelpers::L_PLAIN2_AND_PITCH; + + using OpenSHC::Map::LogicHelpers::L_MOAT; + using OpenSHC::Map::LogicHelpers::L_MOAT_DUG_OR_PLANNED; + using OpenSHC::Map::LogicHelpers::L_PLAIN2_AND_PITCH; + + // FUNCTION: STRONGHOLDCRUSADER 0x00500500 + undefined4 TileMapState::advanceMoatDigProgress(int moatID) + { + this->moats[moatID].fillProgress = this->moats[moatID].fillProgress + 1; + if ((char)this->moats[moatID].fillProgress <= 3) { + return 0; + } + + int tile = this->moats[moatID].tile; + this->moats[moatID].someCountDown = 0; + this->moats[moatID].fillProgress = 4; + this->moats[moatID].stage = 2; + this->HeightLayer[tile] = 0; + this->LogicLayer[this->moats[moatID].tile] + = this->LogicLayer[this->moats[moatID].tile] & ~L_MOAT_DUG_OR_PLANNED; + this->LogicLayer[this->moats[moatID].tile] = this->LogicLayer[this->moats[moatID].tile] & ~L_PLAIN2_AND_PITCH; + this->LogicLayer[this->moats[moatID].tile] = this->LogicLayer[this->moats[moatID].tile] | L_MOAT; + this->Logic2Layer[this->moats[moatID].tile] = 0; + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::updateWalkAndPathLayer, + DAT_PathFindingState::ptr)(2, this->moats[moatID].x, this->moats[moatID].y); + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::updatePathLinkagesInAllEightDirections, + DAT_PathFindingState::ptr)(this->moats[moatID].y, this->moats[moatID].tile); + DAT_PathFindingState::instance.toggleUpdateSeparateAreaTileMap = 1; + MACRO_CALL_MEMBER(OpenSHC::UI::MinimapViewState_Func::triggerMinimapRedraw, DAT_MinimapViewState::ptr)(1); + return 1; + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/applyRockGraphicsToFootprint.cpp b/src/OpenSHC/Map/TileMapState/applyRockGraphicsToFootprint.cpp new file mode 100644 index 0000000000..62c2634400 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/applyRockGraphicsToFootprint.cpp @@ -0,0 +1,61 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Map/LandscapeState.func.hpp" + +#include "OpenSHC/Globals/DAT_LandscapeState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" +#include "OpenSHC/Globals/GMTotalPicturesProcessed.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_WALL_OR_GATEHOUSE; + + // FUNCTION: STRONGHOLDCRUSADER 0x004FB770 + void TileMapState::applyRockGraphicsToFootprint(int rockID) + { + int rockX = DAT_LandscapeState::instance.rocks[rockID].x; + int rockY = DAT_LandscapeState::instance.rocks[rockID].y; + int orientation = DAT_LandscapeState::instance.rocks[rockID].orientation + this->mapOrientation; + if (orientation > 7) { + orientation = orientation - 8; + } + int size = DAT_LandscapeState::instance.rocks[rockID].size; + short surface = (short)(orientation / 2) * size * size; + + int index = 0; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)( + index, DAT_LandscapeState::instance.rocks[rockID].size); + int tile = DAT_ViewportRenderState::instance.translationMatrix[this->buildingY + rockY].addXgetTile + rockX + + this->buildingX; + if ((this->LogicLayer[tile] & L_WALL_OR_GATEHOUSE) == 0) { + if (this->disableElevationRendering == 0) { + this->GfxLayer[tile] + = ((short)GMTotalPicturesProcessed::instance[DAT_LandscapeState::instance.rocks[rockID] + .unknownGMID] + + (short)DAT_LandscapeState::instance.rocks[rockID].gfx + + (short)this->buildingRotationRelatedValue + surface) + - 1; + } else if (DAT_LandscapeState::instance.rocks[rockID].size == 1) { + this->GfxLayer[tile] + = ((short)GMTotalPicturesProcessed::instance[DAT_LandscapeState::instance.rocks[rockID] + .unknownGMID] + + (short)DAT_LandscapeState::instance.rocks[rockID].gfx + + (short)this->buildingRotationRelatedValue + surface) + - 1; + } else { + this->GfxLayer[tile] + = (short)MACRO_CALL_MEMBER(OpenSHC::Map::LandscapeState_Func::getRandomRockImageOffset, + DAT_LandscapeState::ptr)(((byte)this->RandomLayer[tile] & 3) + 1) + + (short) + GMTotalPicturesProcessed::instance[DAT_LandscapeState::instance.rocks[rockID].unknownGMID] + + surface - 1; + } + } + index++; + } while (index < this->constructionTileCount); + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/applyTreeBrushToLogicalLayer.cpp b/src/OpenSHC/Map/TileMapState/applyTreeBrushToLogicalLayer.cpp new file mode 100644 index 0000000000..3de55f20ee --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/applyTreeBrushToLogicalLayer.cpp @@ -0,0 +1,51 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Map/LandscapeState.func.hpp" +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" + +#include "OpenSHC/Globals/DAT_LandscapeState.hpp" +#include "OpenSHC/Globals/DAT_PathFindingState.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_BORDER; + using OpenSHC::Map::LogicHelpers::L_MARSH; + using OpenSHC::Map::LogicHelpers::L_MOAT; + using OpenSHC::Map::LogicHelpers::L_SEA; + using OpenSHC::Map::LogicHelpers::L_TREE_VARIATION; + + // FUNCTION: STRONGHOLDCRUSADER 0x00508DD0 + void TileMapState::applyTreeBrushToLogicalLayer(int treeID, int noVariation) + { + int brushSize = DAT_TerrainDefinedData::instance.BrushSizeArray[MACRO_CALL_MEMBER( + OpenSHC::Map::LandscapeState_Func::getValueFrom0UpTo3ForTreeTypeAndTreeStage, DAT_LandscapeState::ptr)( + DAT_LandscapeState::instance.trees[treeID].treeType, DAT_LandscapeState::instance.trees[treeID].stage)]; + int y = (short)DAT_LandscapeState::instance.trees[treeID].yPosition; + int tileUnk = (short)DAT_LandscapeState::instance.trees[treeID].xPosition + + DAT_ViewportRenderState::instance.translationMatrix[y].addXgetTile; + int baseTile = tileUnk; + int baseY = y; + for (int tileIndex = 0; tileIndex < brushSize; tileIndex++) { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getTileForBrush, this)( + 1, tileIndex, &tileUnk, (int*)&y, baseTile, baseY); + if ((this->LogicLayer[tileUnk] & L_BORDER) != 0) { + break; + } + if ((this->LogicLayer[tileUnk] & (L_SEA | L_MARSH | L_MOAT)) == 0) { + if (noVariation != 0) { + this->LogicLayer[tileUnk] = this->LogicLayer[tileUnk] & ~L_TREE_VARIATION; + } else { + this->LogicLayer[tileUnk] = this->LogicLayer[tileUnk] | L_TREE_VARIATION; + } + } + } + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::updateWalkAndPathLayer, + DAT_PathFindingState::ptr)(7, (short)DAT_LandscapeState::instance.trees[treeID].xPosition, + (short)DAT_LandscapeState::instance.trees[treeID].yPosition); + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/changeMapOrientation.cpp b/src/OpenSHC/Map/TileMapState/changeMapOrientation.cpp new file mode 100644 index 0000000000..dc7c797c69 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/changeMapOrientation.cpp @@ -0,0 +1,57 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Map/Buildings/BuildingsState.func.hpp" +#include "OpenSHC/Rendering/ViewportRenderState.func.hpp" + +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + + // FUNCTION: STRONGHOLDCRUSADER 0x00501B90 + void TileMapState::changeMapOrientation(int mapOrientation) + { + MACRO_CALL_MEMBER(OpenSHC::Rendering::ViewportRenderState_Func::saveFocusTileAndCenterPreview, + DAT_ViewportRenderState::ptr)(); + DAT_TileMapState::instance.mapOrientation = mapOrientation; + MACRO_CALL_MEMBER( + OpenSHC::Rendering::ViewportRenderState_Func::restoreFocusTile, DAT_ViewportRenderState::ptr)(); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::forceFullTileMapRedraw, this)(); + MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::refreshAllBuildingTileDisplays, DAT_BuildingsState::ptr)(); + DAT_BuildingsState::instance.field4_0x10 = 5; + switch (this->mapOrientation) { + case 0: + this->screenSouthEastDirection = 3; + this->orientedRowStep = 1; + this->screenEastDirection = 2; + this->screenSouthDirection = 4; + this->screenSouthWestDirection = 5; + return; + case 2: + this->screenSouthEastDirection = 5; + this->orientedRowStep = 1; + this->screenEastDirection = 4; + this->screenSouthDirection = 6; + this->screenSouthWestDirection = 7; + return; + case 4: + this->screenSouthEastDirection = 7; + this->screenEastDirection = 6; + this->screenSouthDirection = 0; + this->screenSouthWestDirection = 1; + this->orientedRowStep = -1; + return; + case 6: + this->screenSouthEastDirection = 1; + this->screenEastDirection = 0; + this->screenSouthDirection = 2; + this->screenSouthWestDirection = 3; + this->orientedRowStep = -1; + } + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/checkBuildingCanBePlacedHere.cpp b/src/OpenSHC/Map/TileMapState/checkBuildingCanBePlacedHere.cpp new file mode 100644 index 0000000000..7637cb938f --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/checkBuildingCanBePlacedHere.cpp @@ -0,0 +1,886 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Map/Buildings/BuildingsState.func.hpp" +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" +#include "OpenSHC/Rendering/ViewportRenderState.func.hpp" +#include "OpenSHC/Synchrony/GameSynchronyState.func.hpp" +#include "OpenSHC/Commands/MappersEnum.hpp" +#include "OpenSHC/Game/GameMode.hpp" +#include "OpenSHC/Game/GameMode2.hpp" +#include "OpenSHC/Map/Buildings/BuildingFailReasonEnum.hpp" +#include "OpenSHC/Map/Buildings/BuildingType.hpp" +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +#include "OpenSHC/Globals/DAT_BuildingDefinedData.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" +#include "OpenSHC/Globals/DAT_PathFindingState.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Commands::MappersEnum; + using OpenSHC::Game::GameMode; + using OpenSHC::Game::GameMode2; + using OpenSHC::Map::Buildings::BuildingFailReasonEnum; + using OpenSHC::Map::Buildings::BuildingType; + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x005037B0 + void TileMapState::checkBuildingCanBePlacedHere( + int playerID, uint x, uint y__fertileLandCount, MappersEnum commandBuildingType, int buildingSize) + { + uint uVar1; + byte bVar2; + BuildingType _buildingType; + int _buildRange; + BOOLEnum BVar3; + int iVar4; + uint uVar5; + int iVar6; + int iVar7; + MappersEnum _commandBuildingType; + int iVar8; + int* piVar9; + int bVar10; + int bVar11; + int _grassCount; + int _distance; + int _range; + int _boulderCount; + int _ironCount; + int _oilCount; + int local_4; + uint _x; + uint _y; + /* the parameter carries the y position in, then is reused as a tile counter */ + _y = y__fertileLandCount; + _x = x; + local_4 = 0; + int sizeDefaulted = 0; + if (buildingSize < 0) { + buildingSize = 2; + sizeDefaulted = 1; + } + _commandBuildingType = (MappersEnum)(short)(undefined2)commandBuildingType; + this->buildingPlacementFail = FALSE; + this->placementWarning = 0; + this->field127_0x554944 = 0; + this->uiBuildingRotation = 0xf; + _buildingType + = MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::convertCommandBuildingTypeToBuildingType, + DAT_BuildingsState::ptr)(_commandBuildingType); + this->buildingSpriteSheetID_1 + = DAT_BuildingDefinedData::instance.Building_SpriteSheet_ID_Array_1[_buildingType].intValue; + this->buildingSpriteID1 = MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::getSpriteID, DAT_BuildingsState::ptr)(_commandBuildingType); + this->buildingSpriteID2 = MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::getSpriteID2, DAT_BuildingsState::ptr)(_commandBuildingType); + _buildingType + = MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::convertCommandBuildingTypeToBuildingType, + DAT_BuildingsState::ptr)(_commandBuildingType); + this->buildingHeightLimit = DAT_BuildingDefinedData::instance.BuildingPlacement_HeightLimit[_buildingType]; + _buildingType + = MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::convertCommandBuildingTypeToBuildingType, + DAT_BuildingsState::ptr)(_commandBuildingType); + this->buildingMaxHeightDifference + = DAT_BuildingDefinedData::instance.BuildingPlacement_MaxHeightDifference[_buildingType]; + _buildingType + = MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::convertCommandBuildingTypeToBuildingType, + DAT_BuildingsState::ptr)(_commandBuildingType); + this->buildingPlacementProperty_3 + = DAT_BuildingDefinedData::instance.BuildingPlacement_Property_3[_buildingType]; + _buildingType + = MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::convertCommandBuildingTypeToBuildingType, + DAT_BuildingsState::ptr)(_commandBuildingType); + this->buildingPlacementProperty_4 + = DAT_BuildingDefinedData::instance.BuildingPlacement_Property_4[_buildingType]; + if (DAT_GameSynchronyState::instance.currentGameMode == OpenSHC::Game::GM_SOLITARY + || DAT_GameSynchronyState::instance.currentPlayerFullIDArray[playerID] != -1 + || DAT_GameSynchronyState::instance.currentAIArray[playerID] == 0) { + this->buildingPlacementProperty_4 = 0; + } + _buildingType + = MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::convertCommandBuildingTypeToBuildingType, + DAT_BuildingsState::ptr)(_commandBuildingType); + this->buildingPlacementProperty_5 + = DAT_BuildingDefinedData::instance.BuildingPlacement_Property_5[_buildingType]; + _buildingType + = MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::convertCommandBuildingTypeToBuildingType, + DAT_BuildingsState::ptr)(_commandBuildingType); + this->buildingPlacementProperty_6 + = DAT_BuildingDefinedData::instance.BuildingPlacement_Property_6[_buildingType]; + _buildingType + = MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::convertCommandBuildingTypeToBuildingType, + DAT_BuildingsState::ptr)(_commandBuildingType); + this->buildingPlacementProperty_7 + = DAT_BuildingDefinedData::instance.BuildingPlacement_Property_7[_buildingType]; + if ((undefined2)commandBuildingType == OpenSHC::Commands::M_MAPPER_SIEGE_TOWER_BASE) { + return; + } + _boulderCount = 0; + _ironCount = 0; + _oilCount = 0; + y__fertileLandCount = 0; + _grassCount = 0; + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::storeMinAndMaxHeightOfArea, this)(x, _y, buildingSize); + if (sizeDefaulted != 0) + goto switchD_0050397c_caseD_33; + if (0x138 < (int)_commandBuildingType) { + if (325 < (int)_commandBuildingType) { + if ((int)_commandBuildingType < 328) + goto switchD_0050397c_caseD_33; + if (_commandBuildingType == 358) + goto switchD_0050397c_caseD_be; + } + switchD_0050397c_caseD_35: + if ((DAT_GameCore::instance.gameMode_2 != OpenSHC::Game::GM_EDITOR) + && (DAT_GameCore::instance.gameMode_2 != OpenSHC::Game::GM_SIEGE_THAT)) { + bVar10 = DAT_GameSynchronyState::instance.currentGameMode != OpenSHC::Game::GM_SOLITARY; + bVar11 = true; + x = 0; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)( + x, buildingSize); + BVar3 = MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::isEnemyTooCloseUnk, + DAT_PathFindingState::ptr)(playerID, this->buildingX + _x, this->buildingY + _y, + (int)((-(uint)bVar10 & 0xfffffff1) + 0x1e)); + if (BVar3 != FALSE) { + this->buildingPlacementFailReason = ((BuildingFailReasonEnum)0x11); + bVar11 = false; + break; + } + x = x + 1; + } while ((int)x < this->constructionTileCount); + BVar3 = MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::isSignPostWithinDistance, + DAT_PathFindingState::ptr)(_x, _y, DAT_GameState::instance.mapAndTime.unk_signpostDistance + 5); + if (BVar3 == FALSE) { + if (bVar11) + goto LAB_00503d46; + } else { + this->buildingPlacementFailReason = ((BuildingFailReasonEnum)0x15); + } + LAB_00503d3c: + this->buildingPlacementFail = TRUE; + } + goto LAB_00503d46; + } + if (_commandBuildingType == OpenSHC::Commands::M_MAPPER_DOG_CAGE) { + if (9 < DAT_GameState::instance.playerDataArray[playerID].dogCageCount) { + this->buildingPlacementFail = TRUE; + this->buildingPlacementFailReason = ((BuildingFailReasonEnum)1000); + return; + } + switchD_0050397c_caseD_62: + local_4 = 5; + switchD_0050397c_caseD_64: + if (DAT_GameCore::instance.gameMode_2 == OpenSHC::Game::GM_EDITOR) { + iVar8 = 0; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)( + iVar8, buildingSize); + iVar4 + = MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::isOpponentBuildingInRange, + DAT_PathFindingState::ptr)( + playerID, (int)(this->buildingX + x), (int)(this->buildingY + _y), 7, -1, -1, -1); + if (iVar4 != 0) + goto LAB_005039d6; + iVar8 = iVar8 + 1; + } while (iVar8 < this->constructionTileCount); + } else if (DAT_GameCore::instance.gameMode_2 != OpenSHC::Game::GM_SIEGE_THAT) { + if (DAT_GameSynchronyState::instance.currentGameMode == OpenSHC::Game::GM_SOLITARY) { + _distance = 30; + _range = 30; + } else { + MACRO_CALL_MEMBER( + OpenSHC::Synchrony::GameSynchronyState_Func::isAIPlayer, DAT_GameSynchronyState::ptr)(playerID); + _distance = 15; + _range = 7; + } + x = 0; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)( + x, buildingSize); + BVar3 = MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::isEnemyTooCloseUnk, + DAT_PathFindingState::ptr)(playerID, this->buildingX + _x, this->buildingY + _y, _distance); + if (BVar3 != FALSE) { + LAB_00503b32: + this->buildingPlacementFailReason = ((BuildingFailReasonEnum)0x11); + LAB_00503b48: + bVar11 = false; + break; + } + if (DAT_GameSynchronyState::instance.currentGameMode != OpenSHC::Game::GM_SOLITARY) { + iVar8 = MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::PathFindingState_Func::isOpponentBuildingInRange, + DAT_PathFindingState::ptr)( + playerID, (int)(this->buildingX + _x), (int)(this->buildingY + _y), _range, -1, -1, -1); + if (iVar8 != 0) + goto LAB_00503b32; + _buildRange + = MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getCastleBuildRangeForMapSize, this)(); + iVar8 = MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::PathFindingState_Func::isTileInRangeOfKeepRange, + DAT_PathFindingState::ptr)( + playerID, this->buildingX + _x, this->buildingY + _y, _buildRange + local_4); + if (iVar8 == 0) + goto LAB_00503b11; + this->buildingPlacementFailReason = ((BuildingFailReasonEnum)0x12); + goto LAB_00503b48; + } + LAB_00503b11: + x = x + 1; + bVar11 = true; + } while ((int)x < this->constructionTileCount); + BVar3 = MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::isSignPostWithinDistance, + DAT_PathFindingState::ptr)(_x, _y, DAT_GameState::instance.mapAndTime.unk_signpostDistance + 5); + if (BVar3 == FALSE) { + if (bVar11) + goto LAB_00503d46; + } else { + this->buildingPlacementFailReason = ((BuildingFailReasonEnum)0x15); + } + this->buildingPlacementFail = TRUE; + if (this->buildingPlacementFailReason == OpenSHC::Map::Buildings::BFRE_DEFAULT_CANT_PLACE_THAT_THERE) { + this->buildingPlacementFailReason = ((BuildingFailReasonEnum)0x12); + } + } + } else { + switch (_commandBuildingType) { + case OpenSHC::Commands::M_MAPPER_WOODSMAN: + case OpenSHC::Commands::M_MAPPER_OXENBASE: + case OpenSHC::Commands::M_MAPPER_QUARRY: + case OpenSHC::Commands::M_MAPPER_TUNNEL: + case OpenSHC::Commands::M_MAPPER_TUNNEL_CONSTRUCTION: + case OpenSHC::Commands::M_MAPPER_WHEATFARM: + case OpenSHC::Commands::M_MAPPER_HOPSFARM: + case OpenSHC::Commands::M_MAPPER_APPLEFARM: + case OpenSHC::Commands::M_MAPPER_CATTLEFARM: + case OpenSHC::Commands::M_MAPPER_IRON_MINE: + case OpenSHC::Commands::M_MAPPER_PITCH_WORKINGS: + case OpenSHC::Commands::M_MAPPER_QUARRYPILE: + goto switchD_0050397c_caseD_33; + case OpenSHC::Commands::M_MAPPER_STORES: + case OpenSHC::Commands::M_MAPPER_GRANARY: + case OpenSHC::Commands::M_MAPPER_ARMOURY: + if (DAT_GameSynchronyState::instance.currentGameMode != OpenSHC::Game::GM_SOLITARY) { + iVar8 = 0; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)( + iVar8, buildingSize); + BVar3 = MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::isEnemyTooCloseUnk, + DAT_PathFindingState::ptr)(playerID, this->buildingX + x, this->buildingY + _y, 3); + if (BVar3 != FALSE) + goto LAB_005039d6; + iVar8 = iVar8 + 1; + } while (iVar8 < this->constructionTileCount); + } + break; + default: + goto switchD_0050397c_caseD_35; + case OpenSHC::Commands::M_MAPPER_KILLING_PIT: + case OpenSHC::Commands::M_MAPPER_PITCH_DITCH: + case OpenSHC::Commands::M_MAPPER_DRAWBRIDGE: + goto switchD_0050397c_caseD_62; + case OpenSHC::Commands::M_MAPPER_GATEHOUSE: + case OpenSHC::Commands::M_MAPPER_GATE_MAIN: + case OpenSHC::Commands::M_MAPPER_GATE_INNER: + case OpenSHC::Commands::M_MAPPER_GATE_WOOD: + case OpenSHC::Commands::M_MAPPER_GATE_POSTERN: + case OpenSHC::Commands::M_MAPPER_MOAT: + case OpenSHC::Commands::M_MAPPER_ANTIMOAT: + case OpenSHC::Commands::M_MAPPER_TOWER1: + case OpenSHC::Commands::M_MAPPER_TOWER2: + case OpenSHC::Commands::M_MAPPER_TOWER3: + case OpenSHC::Commands::M_MAPPER_TOWER4: + case OpenSHC::Commands::M_MAPPER_TOWER5: + case OpenSHC::Commands::M_MAPPER_GATE_WOOD1A: + case OpenSHC::Commands::M_MAPPER_GATE_WOOD1B: + case OpenSHC::Commands::M_MAPPER_GATE_WOOD1C: + case OpenSHC::Commands::M_MAPPER_GATE_WOOD1D: + case OpenSHC::Commands::M_MAPPER_GATE_STONE1A: + case OpenSHC::Commands::M_MAPPER_GATE_STONE1B: + case OpenSHC::Commands::M_MAPPER_GATE_STONE2A: + case OpenSHC::Commands::M_MAPPER_GATE_STONE2B: + goto switchD_0050397c_caseD_64; + case OpenSHC::Commands::M_MAPPER_CATAPULT: + case OpenSHC::Commands::M_MAPPER_TREBUCHET: + case OpenSHC::Commands::M_MAPPER_SIEGE_TOWER: + case OpenSHC::Commands::M_MAPPER_BATTERING_RAM: + case OpenSHC::Commands::M_MAPPER_PORTABLE_SHIELD: + switchD_0050397c_caseD_be: + if ((DAT_GameCore::instance.gameMode_2 != OpenSHC::Game::GM_EDITOR) + && (DAT_GameCore::instance.gameMode_2 != OpenSHC::Game::GM_SIEGE_THAT)) { + iVar8 = 0; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)( + iVar8, buildingSize); + BVar3 = MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::isEnemyTooCloseUnk, + DAT_PathFindingState::ptr)(playerID, this->buildingX + x, this->buildingY + _y, 3); + if (BVar3 != FALSE) + goto LAB_005039d6; + iVar8 = iVar8 + 1; + } while (iVar8 < this->constructionTileCount); + } + } + } + LAB_00503d46: + if (this->buildingPlacementFail == FALSE) { + iVar8 = 0; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)( + iVar8, buildingSize); + iVar4 = MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::findSomeSuitableLocationUnk, + DAT_PathFindingState::ptr)(playerID, this->buildingX + _x, this->buildingY + _y, 2); + if (iVar4 != 0) { + this->buildingPlacementFailReason = ((BuildingFailReasonEnum)0x11); + this->buildingPlacementFail = TRUE; + break; + } + iVar8 = iVar8 + 1; + } while (iVar8 < this->constructionTileCount); + } + switchD_0050397c_caseD_33: + if ((undefined2)commandBuildingType == OpenSHC::Commands::M_MAPPER_DRAWBRIDGE + && 0xc < this->buildingMaxHeight) { + this->buildingPlacementFail = TRUE; + } + x = 0; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)(x, buildingSize); + uVar5 = this->buildingY + _y; + if (399 < this->buildingX + _x) { + this->buildingPlacementFail = 2; + return; + } + if (399 < uVar5) { + this->buildingPlacementFail = 2; + return; + } + if (*(char*)(uVar5 * 400 + 0x21aec98 + this->buildingX + _x) == '\0') { + this->buildingPlacementFail = 2; + return; + } + iVar8 = DAT_ViewportRenderState::instance.translationMatrix[uVar5].addXgetTile + this->buildingX + _x; + uVar5 = this->LogicLayer[iVar8]; + if ((uVar5 & 0x30) != 0) { + this->buildingPlacementFail = 2; + return; + } + if ((uVar5 & 0x20000) != 0) { + _boulderCount = _boulderCount + 1; + } + if ((uVar5 & 0x80000) != 0) { + _ironCount = _ironCount + 1; + } + if ((int)uVar5 < 0) { + _oilCount = _oilCount + 1; + } + if ((uVar5 & 0x100000) == 0) { + bVar2 = this->Logic2Layer[iVar8]; + if ((bVar2 & 0x10) != 0) { + /* + grass + */ + y__fertileLandCount = y__fertileLandCount + 1; + _grassCount = _grassCount + 1; + } + if ((char)bVar2 < '\0') { + /* + thick scrub + */ + y__fertileLandCount = y__fertileLandCount + 1; + _grassCount = _grassCount + 1; + } + if ((bVar2 & 1) != 0) { + /* + scrub + */ + y__fertileLandCount = y__fertileLandCount + 1; + } + } + iVar8 = MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::isBuildingPlacementAllowedAtTile, this)( + iVar8, playerID, _commandBuildingType, 0); + if (iVar8 != 0) { + this->buildingPlacementFail = TRUE; + } + x = x + 1; + } while ((int)x < this->constructionTileCount); + if ((undefined2)commandBuildingType == OpenSHC::Commands::M_MAPPER_CATTLEFARM + || (undefined2)commandBuildingType == OpenSHC::Commands::M_MAPPER_WHEATFARM + || (undefined2)commandBuildingType == OpenSHC::Commands::M_MAPPER_HOPSFARM + || (undefined2)commandBuildingType == OpenSHC::Commands::M_MAPPER_APPLEFARM) { + if ((int)y__fertileLandCount < this->constructionTileCount) { + this->buildingPlacementFailReason = ((BuildingFailReasonEnum)0x16); + this->buildingPlacementFail = TRUE; + return; + } + if (_grassCount < 50) { + this->buildingPlacementFailReason = ((BuildingFailReasonEnum)0x17); + this->buildingPlacementFail = TRUE; + } + } else { + if ((undefined2)commandBuildingType != OpenSHC::Commands::M_MAPPER_QUARRY) { + if ((undefined2)commandBuildingType == OpenSHC::Commands::M_MAPPER_KEEP1 + || (undefined2)commandBuildingType == OpenSHC::Commands::M_MAPPER_KEEP2 + || (undefined2)commandBuildingType == OpenSHC::Commands::M_MAPPER_KEEP3) { + buildingSize = (_commandBuildingType - OpenSHC::Commands::M_MAPPER_KEEP1) * 0x60 + 0xb491b8; + commandBuildingType = OpenSHC::Commands::M_MAPPER_NULL; + do { + uVar5 = *(int*)(buildingSize + 4) + _y; + BVar3 = MACRO_CALL_MEMBER(OpenSHC::Rendering::ViewportRenderState_Func::xyAreValid, + DAT_ViewportRenderState::ptr)(*(int*)buildingSize + _x, uVar5); + if (BVar3 == FALSE) { + this->buildingPlacementFail = 2; + return; + } + iVar8 = DAT_ViewportRenderState::instance.translationMatrix[uVar5].addXgetTile + + *(int*)buildingSize + _x; + if ((this->LogicLayer[iVar8] & 0x30) != 0) { + this->buildingPlacementFail = 2; + return; + } + iVar8 = MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::isBuildingPlacementAllowedAtTile, + this)(iVar8, playerID, _commandBuildingType, 0); + if (iVar8 != 0) { + this->buildingPlacementFail = TRUE; + } + buildingSize = buildingSize + 8; + commandBuildingType = (MappersEnum)(commandBuildingType + OpenSHC::Commands::M_MAPPER_AREA); + } while ((int)commandBuildingType < 3); + iVar4 = (_commandBuildingType - OpenSHC::Commands::M_MAPPER_KEEP1) * 0x20; + iVar6 = _x + *(int*)((int)DAT_TerrainDefinedData::ptr + iVar4 + 900); + iVar8 = *(int*)((int)DAT_TerrainDefinedData::ptr + iVar4 + 904); + x = 0; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)(x, 7); + uVar5 = this->buildingY + _y + iVar8; + uVar1 = this->buildingX + iVar6; + if (399 < uVar1) { + this->buildingPlacementFail = 2; + return; + } + if (399 < uVar5) { + this->buildingPlacementFail = 2; + return; + } + if (*(char*)(uVar5 * 400 + 0x21aec98 + uVar1) == '\0') { + this->buildingPlacementFail = 2; + return; + } + iVar7 = DAT_ViewportRenderState::instance.translationMatrix[uVar5].addXgetTile + this->buildingX + + iVar6; + if ((this->LogicLayer[iVar7] & 0x30) != 0) { + this->buildingPlacementFail = 2; + return; + } + iVar7 = MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::isBuildingPlacementAllowedAtTile, + this)(iVar7, playerID, _commandBuildingType, 0); + if (iVar7 != 0) { + this->buildingPlacementFail = TRUE; + } + x = x + 1; + } while ((int)x < this->constructionTileCount); + iVar8 = *(int*)((int)DAT_TerrainDefinedData::ptr + iVar4 + 1000); + iVar4 = *(int*)((int)DAT_TerrainDefinedData::ptr + iVar4 + 0x3e4) + _x; + x = 0; + while (true) { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)(x, 5); + iVar6 = this->buildingX; + uVar5 = this->buildingY + iVar8 + _y; + BVar3 = MACRO_CALL_MEMBER(OpenSHC::Rendering::ViewportRenderState_Func::xyAreValid, + DAT_ViewportRenderState::ptr)(iVar4 + this->buildingX, uVar5); + if ((BVar3 == FALSE) + || (iVar6 = DAT_ViewportRenderState::instance.translationMatrix[uVar5].addXgetTile + iVar6 + + iVar4, + (this->LogicLayer[iVar6] & 0x30) != 0)) + break; + iVar6 = MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::isBuildingPlacementAllowedAtTile, + this)(iVar6, playerID, _commandBuildingType, 0); + if (iVar6 != 0) { + this->buildingPlacementFail = TRUE; + } + x = x + 1; + if (this->constructionTileCount <= (int)x) { + return; + } + } + } else { + if ((undefined2)commandBuildingType != OpenSHC::Commands::M_MAPPER_GATE_WOOD1A + && (undefined2)commandBuildingType != OpenSHC::Commands::M_MAPPER_GATE_WOOD1B + && (undefined2)commandBuildingType != OpenSHC::Commands::M_MAPPER_GATE_WOOD1C + && (undefined2)commandBuildingType != OpenSHC::Commands::M_MAPPER_GATE_WOOD1D) { + if ((undefined2)commandBuildingType == OpenSHC::Commands::M_MAPPER_IRON_MINE) { + if (3 < _ironCount) { + return; + } + this->buildingPlacementFailReason = OpenSHC::Map::Buildings::BFRE_NOT_IRON_ORE; + this->buildingPlacementFail = TRUE; + return; + } + if ((undefined2)commandBuildingType == OpenSHC::Commands::M_MAPPER_PITCH_WORKINGS) { + if (0 < _oilCount) { + return; + } + this->buildingPlacementFailReason = OpenSHC::Map::Buildings::BFRE_NOT_OIL_MARSH; + this->buildingPlacementFail = TRUE; + return; + } + if ((undefined2)commandBuildingType == OpenSHC::Commands::M_MAPPER_STORES) { + if (DAT_GameState::instance.playerDataArray[playerID].stockpile.id == 0) { + return; + } + iVar8 + = MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::getEmptyBuildingCount, + DAT_BuildingsState::ptr)(playerID, OpenSHC::Map::Buildings::BT_STOCKPILE); + if (iVar8 < 0x20) { + BVar3 = MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::hasBuildingAsNeighbour, + DAT_BuildingsState::ptr)(playerID, (int)(_x), (int)(_y), buildingSize, + OpenSHC::Map::Buildings::BT_STOCKPILE); + if (BVar3 != FALSE) { + return; + } + this->buildingPlacementFail = TRUE; + this->buildingPlacementFailReason = OpenSHC::Map::Buildings::BFRE_NOT_ADJ_STOCKPILE; + return; + } + this->buildingPlacementFail = TRUE; + return; + } + if ((undefined2)commandBuildingType == OpenSHC::Commands::M_MAPPER_GRANARY) { + if (DAT_GameState::instance.playerDataArray[playerID].granary.id == 0) { + return; + } + iVar8 + = MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::getEmptyBuildingCount, + DAT_BuildingsState::ptr)(playerID, OpenSHC::Map::Buildings::BT_GRANARY); + if (iVar8 < 8) { + BVar3 = MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::hasBuildingAsNeighbour, + DAT_BuildingsState::ptr)( + playerID, (int)(_x), (int)(_y), buildingSize, OpenSHC::Map::Buildings::BT_GRANARY); + if (BVar3 != FALSE) { + return; + } + this->buildingPlacementFail = TRUE; + this->buildingPlacementFailReason = OpenSHC::Map::Buildings::BFRE_NOT_ADJ_GRANARY; + return; + } + this->buildingPlacementFail = TRUE; + return; + } + if ((undefined2)commandBuildingType == OpenSHC::Commands::M_MAPPER_ARMOURY) { + if (DAT_GameState::instance.playerDataArray[playerID].armory.id == 0) { + return; + } + iVar8 + = MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::getEmptyBuildingCount, + DAT_BuildingsState::ptr)(playerID, OpenSHC::Map::Buildings::BT_ARMORY); + if (iVar8 < 8) { + BVar3 = MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::hasBuildingAsNeighbour, + DAT_BuildingsState::ptr)( + playerID, (int)(_x), (int)(_y), buildingSize, OpenSHC::Map::Buildings::BT_ARMORY); + if (BVar3 != FALSE) { + return; + } + this->buildingPlacementFail = TRUE; + this->buildingPlacementFailReason = OpenSHC::Map::Buildings::BFRE_NOT_ADJ_ARMORY; + return; + } + this->buildingPlacementFail = TRUE; + return; + } + if ((undefined2)commandBuildingType == OpenSHC::Commands::M_MAPPER_BARRACKS_EURO + || (undefined2)commandBuildingType == OpenSHC::Commands::M_MAPPER_BARRACKS_ARAB) { + iVar4 = _x + + DAT_TerrainDefinedData::instance + .BuildingPartsOffsets[this->DAT_TempBuildingRotation][0] + .x; + iVar8 = DAT_TerrainDefinedData::instance + .BuildingPartsOffsets[this->DAT_TempBuildingRotation][0] + .y; + x = 0; + while (true) { + MACRO_CALL_MEMBER( + OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)(x, 5); + uVar5 = this->buildingY + _y + iVar8; + BVar3 = MACRO_CALL_MEMBER(OpenSHC::Rendering::ViewportRenderState_Func::xyAreValid, + DAT_ViewportRenderState::ptr)(this->buildingX + iVar4, uVar5); + if (BVar3 == FALSE) { + this->buildingPlacementFail = 2; + return; + } + iVar6 = DAT_ViewportRenderState::instance.translationMatrix[uVar5].addXgetTile + + this->buildingX + iVar4; + if ((this->LogicLayer[iVar6] & 0x30) != 0) + break; + iVar6 = MACRO_CALL_MEMBER( + OpenSHC::Map::TileMapState_Func::isBuildingPlacementAllowedAtTile, this)( + iVar6, playerID, _commandBuildingType, 0); + if (iVar6 != 0) { + this->buildingPlacementFail = TRUE; + } + x = x + 1; + if (this->constructionTileCount <= (int)x) { + iVar4 = DAT_TerrainDefinedData::instance + .BuildingPartsOffsets[this->DAT_TempBuildingRotation][1] + .x + + _x; + iVar8 = DAT_TerrainDefinedData::instance + .BuildingPartsOffsets[this->DAT_TempBuildingRotation][1] + .y; + x = 0; + while (true) { + MACRO_CALL_MEMBER( + OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)( + x, 5); + iVar6 = this->buildingX; + uVar5 = this->buildingY + iVar8 + _y; + BVar3 = MACRO_CALL_MEMBER( + OpenSHC::Rendering::ViewportRenderState_Func::xyAreValid, + DAT_ViewportRenderState::ptr)(this->buildingX + iVar4, uVar5); + if (BVar3 == FALSE) { + this->buildingPlacementFail = 2; + return; + } + iVar6 = DAT_ViewportRenderState::instance.translationMatrix[uVar5].addXgetTile + + iVar6 + iVar4; + if ((this->LogicLayer[iVar6] & 0x30) != 0) + break; + iVar6 = MACRO_CALL_MEMBER( + OpenSHC::Map::TileMapState_Func::isBuildingPlacementAllowedAtTile, this)( + iVar6, playerID, _commandBuildingType, 0); + if (iVar6 != 0) { + this->buildingPlacementFail = TRUE; + } + x = x + 1; + if (this->constructionTileCount <= (int)x) { + iVar4 = DAT_TerrainDefinedData::instance + .BuildingPartsOffsets[this->DAT_TempBuildingRotation][2] + .x + + _x; + iVar8 = DAT_TerrainDefinedData::instance + .BuildingPartsOffsets[this->DAT_TempBuildingRotation][2] + .y; + x = 0; + while (true) { + MACRO_CALL_MEMBER( + OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, + this)(x, 5); + iVar6 = this->buildingX; + uVar5 = this->buildingY + iVar8 + _y; + BVar3 = MACRO_CALL_MEMBER( + OpenSHC::Rendering::ViewportRenderState_Func::xyAreValid, + DAT_ViewportRenderState::ptr)(this->buildingX + iVar4, uVar5); + if (BVar3 == FALSE) { + this->buildingPlacementFail = 2; + return; + } + iVar6 = DAT_ViewportRenderState::instance.translationMatrix[uVar5] + .addXgetTile + + iVar6 + iVar4; + if ((this->LogicLayer[iVar6] & 0x30) != 0) + break; + iVar6 = MACRO_CALL_MEMBER( + OpenSHC::Map::TileMapState_Func::isBuildingPlacementAllowedAtTile, + this)(iVar6, playerID, _commandBuildingType, 0); + if (iVar6 != 0) { + this->buildingPlacementFail = TRUE; + } + x = x + 1; + if (this->constructionTileCount <= (int)x) { + return; + } + } + this->buildingPlacementFail = 2; + return; + } + } + this->buildingPlacementFail = 2; + return; + } + } + this->buildingPlacementFail = 2; + return; + } + if ((undefined2)commandBuildingType == OpenSHC::Commands::M_MAPPER_ENGINEERS_GUILD + || (undefined2)commandBuildingType == OpenSHC::Commands::M_MAPPER_TUNNELERS_GUILD) { + iVar4 = _x + + DAT_TerrainDefinedData::instance + .BuildingPartsOffsets[this->DAT_TempBuildingRotation][1] + .x; + iVar8 = DAT_TerrainDefinedData::instance + .BuildingPartsOffsets[this->DAT_TempBuildingRotation][1] + .y; + x = 0; + while (true) { + MACRO_CALL_MEMBER( + OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)(x, 5); + uVar5 = this->buildingY + _y + iVar8; + BVar3 = MACRO_CALL_MEMBER(OpenSHC::Rendering::ViewportRenderState_Func::xyAreValid, + DAT_ViewportRenderState::ptr)(this->buildingX + iVar4, uVar5); + if (BVar3 == FALSE) { + this->buildingPlacementFail = 2; + return; + } + iVar6 = DAT_ViewportRenderState::instance.translationMatrix[uVar5].addXgetTile + + this->buildingX + iVar4; + if ((this->LogicLayer[iVar6] & 0x30) != 0) + break; + iVar6 = MACRO_CALL_MEMBER( + OpenSHC::Map::TileMapState_Func::isBuildingPlacementAllowedAtTile, this)( + iVar6, playerID, _commandBuildingType, 0); + if (iVar6 != 0) { + this->buildingPlacementFail = TRUE; + } + x = x + 1; + if (this->constructionTileCount <= (int)x) { + return; + } + } + this->buildingPlacementFail = 2; + return; + } + if ((undefined2)commandBuildingType == OpenSHC::Commands::M_MAPPER_OIL_SMELTER) { + iVar4 + = _x + DAT_TerrainDefinedData::instance.field63_0x19c[this->DAT_TempBuildingRotation].x; + iVar8 = DAT_TerrainDefinedData::instance.field63_0x19c[this->DAT_TempBuildingRotation].y; + x = 0; + while (true) { + MACRO_CALL_MEMBER( + OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)(x, 4); + uVar5 = this->buildingY + _y + iVar8; + BVar3 = MACRO_CALL_MEMBER(OpenSHC::Rendering::ViewportRenderState_Func::xyAreValid, + DAT_ViewportRenderState::ptr)(this->buildingX + iVar4, uVar5); + if (BVar3 == FALSE) { + this->buildingPlacementFail = 2; + return; + } + iVar6 = DAT_ViewportRenderState::instance.translationMatrix[uVar5].addXgetTile + + this->buildingX + iVar4; + if ((this->LogicLayer[iVar6] & 0x30) != 0) + break; + iVar6 = MACRO_CALL_MEMBER( + OpenSHC::Map::TileMapState_Func::isBuildingPlacementAllowedAtTile, this)( + iVar6, playerID, OpenSHC::Commands::M_MAPPER_OIL_SMELTER, 0); + if (iVar6 != 0) { + this->buildingPlacementFail = TRUE; + } + x = x + 1; + if (this->constructionTileCount <= (int)x) { + return; + } + } + this->buildingPlacementFail = 2; + return; + } + if ((undefined2)commandBuildingType != OpenSHC::Commands::M_MAPPER_TUNNEL_CONSTRUCTION) { + return; + } + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::algTunnelerFindTarget, + DAT_PathFindingState::ptr)(playerID, 0, (int)(76), (int)(_x), (int)(_y)); + if (DAT_PathFindingState::instance.ALG_TargetTile != 0) { + return; + } + this->buildingPlacementFail = TRUE; + return; + } + iVar8 = _commandBuildingType * 3 + -0x1a4; + iVar6 = _x + *(int*)((int)DAT_TerrainDefinedData::ptr + iVar8 * 8 + 0x56c); + iVar8 = iVar8 * 8; + iVar4 = *(int*)((int)DAT_TerrainDefinedData::ptr + iVar8 + 0x570); + x = 0; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)(x, 3); + uVar5 = this->buildingY + _y + iVar4; + BVar3 = MACRO_CALL_MEMBER(OpenSHC::Rendering::ViewportRenderState_Func::xyAreValid, + DAT_ViewportRenderState::ptr)(this->buildingX + iVar6, uVar5); + if (BVar3 == FALSE) { + this->buildingPlacementFail = 2; + return; + } + iVar7 = DAT_ViewportRenderState::instance.translationMatrix[uVar5].addXgetTile + this->buildingX + + iVar6; + if ((this->LogicLayer[iVar7] & 0x30) != 0) { + this->buildingPlacementFail = 2; + return; + } + iVar7 = MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::isBuildingPlacementAllowedAtTile, + this)(iVar7, playerID, _commandBuildingType, 0); + if (iVar7 != 0) { + this->buildingPlacementFail = TRUE; + } + x = x + 1; + } while ((int)x < this->constructionTileCount); + iVar4 = *(int*)((int)DAT_TerrainDefinedData::ptr + iVar8 + 0x57c); + iVar8 = *(int*)((int)DAT_TerrainDefinedData::ptr + iVar8 + 0x578) + _x; + x = 0; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)(x, 3); + iVar6 = this->buildingX; + uVar5 = this->buildingY + iVar4 + _y; + BVar3 = MACRO_CALL_MEMBER(OpenSHC::Rendering::ViewportRenderState_Func::xyAreValid, + DAT_ViewportRenderState::ptr)(iVar8 + this->buildingX, uVar5); + if (BVar3 == FALSE) { + this->buildingPlacementFail = 2; + return; + } + iVar6 = DAT_ViewportRenderState::instance.translationMatrix[uVar5].addXgetTile + iVar6 + iVar8; + if ((this->LogicLayer[iVar6] & 0x30) != 0) { + this->buildingPlacementFail = 2; + return; + } + iVar6 = MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::isBuildingPlacementAllowedAtTile, + this)(iVar6, playerID, _commandBuildingType, 0); + if (iVar6 != 0) { + this->buildingPlacementFail = TRUE; + } + x = x + 1; + } while ((int)x < this->constructionTileCount); + commandBuildingType = OpenSHC::Commands::M_MAPPER_NULL; + piVar9 + = (int*)((int)DAT_TerrainDefinedData::ptr + (_commandBuildingType * 3 + -0x1a4) * 0x10 + 0x5cc); + while (true) { + iVar8 = piVar9[1]; + iVar4 = *piVar9; + BVar3 = MACRO_CALL_MEMBER(OpenSHC::Rendering::ViewportRenderState_Func::xyAreValid, + DAT_ViewportRenderState::ptr)(_x + iVar4, iVar8 + _y); + if ((BVar3 == FALSE) + || (iVar8 = DAT_ViewportRenderState::instance.translationMatrix[iVar8 + _y].addXgetTile + + iVar4 + _x, + (this->LogicLayer[iVar8] & 0x30) != 0)) + break; + iVar8 = MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::isBuildingPlacementAllowedAtTile, + this)(iVar8, playerID, _commandBuildingType, 0); + if (iVar8 != 0) { + this->buildingPlacementFail = TRUE; + } + commandBuildingType = (MappersEnum)(commandBuildingType + OpenSHC::Commands::M_MAPPER_AREA); + piVar9 = piVar9 + 2; + if (5 < (int)commandBuildingType) { + return; + } + } + } + this->buildingPlacementFail = 2; + return; + } + if (_boulderCount < 8) { + this->buildingPlacementFail = TRUE; + return; + } + } + return; + LAB_005039d6: + this->buildingPlacementFailReason = ((BuildingFailReasonEnum)0x11); + goto LAB_00503d3c; + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/checkDrawbridgePlacement.cpp b/src/OpenSHC/Map/TileMapState/checkDrawbridgePlacement.cpp new file mode 100644 index 0000000000..4e8b2f3f14 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/checkDrawbridgePlacement.cpp @@ -0,0 +1,100 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Map/Buildings/BuildingLogicalState.hpp" +#include "OpenSHC/Map/Buildings/BuildingType.hpp" +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_BORDER; + using OpenSHC::Map::LogicHelpers::L_BORDER_EDGE; + + using OpenSHC::Map::Buildings::BuildingLogicalState; + using OpenSHC::Map::Buildings::BuildingType; + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x004FA2D0 + void TileMapState::checkDrawbridgePlacement(int x, int y) + { + if (this->buildingPlacementFail != FALSE) { + return; + } + this->buildingPlacementFail = TRUE; + + int rotation; + for (rotation = 0; rotation < 4; rotation++) { + int buildings[9]; + int count = 0; + do { + uint offsetY = y + DAT_TerrainDefinedData::instance.drawBridgeOffsets[rotation][count].y; + int offsetX = DAT_TerrainDefinedData::instance.drawBridgeOffsets[rotation][count].x; + uint tileX = offsetX + x; + buildings[count] = 0; + if (tileX > 399 || offsetY > 399) { + break; + } + if (DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[offsetY * 400 + tileX] == 0) { + break; + } + int tileUnk = DAT_ViewportRenderState::instance.translationMatrix[offsetY].addXgetTile + offsetX + x; + if ((this->LogicLayer[tileUnk] & (L_BORDER | L_BORDER_EDGE)) != 0) { + break; + } + buildings[count] = this->BuildingLayer[tileUnk]; + count++; + } while (count < 9); + + if (buildings[0] == 0) { + continue; + } + if (DAT_BuildingsState::instance.buildings[buildings[0]].logicalState + != OpenSHC::Map::Buildings::BLS_NORMAL) { + continue; + } + int span; + if (DAT_BuildingsState::instance.buildings[buildings[0]].buildingType + == OpenSHC::Map::Buildings::BT_GATEHOUSELARGE) { + span = 7; + } else { + if (DAT_BuildingsState::instance.buildings[buildings[0]].buildingType + != OpenSHC::Map::Buildings::BT_GATEHOUSESMALL) { + continue; + } + span = 5; + } + /* the gatehouse faces along one axis, so only two of the four rotations can carry a bridge */ + if (DAT_BuildingsState::instance.buildings[buildings[0]].buildingVariation == 0x51) { + if (rotation == 1 || rotation == 3) { + continue; + } + } else if (DAT_BuildingsState::instance.buildings[buildings[0]].buildingVariation == 0x50) { + if (rotation == 0 || rotation == 2) { + continue; + } + } + + int i = 0; + int matching = 0; + for (; i < span; i++) { + if (buildings[i] == buildings[0]) { + matching++; + } + } + if (matching == span) { + goto found; + } + } + return; + found: + this->uiBuildingRotation = rotation * 2; + this->field127_0x554944 = this->uiBuildingRotation * 25; + this->buildingPlacementFail = FALSE; + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/clearBuildingDisplayFlagsAndEntities.cpp b/src/OpenSHC/Map/TileMapState/clearBuildingDisplayFlagsAndEntities.cpp new file mode 100644 index 0000000000..71140eb177 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/clearBuildingDisplayFlagsAndEntities.cpp @@ -0,0 +1,34 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Map/Entities/EntityState.func.hpp" + +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_EntityState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + + // FUNCTION: STRONGHOLDCRUSADER 0x004FB360 + void TileMapState::clearBuildingDisplayFlagsAndEntities(int buildingID, int param_2) + { + int buildingSizeTileIndex = 0; + int buildingX = DAT_BuildingsState::instance.buildings[buildingID].x; + int buildingY = DAT_BuildingsState::instance.buildings[buildingID].y; + uint widthOrHeight = DAT_BuildingsState::instance.buildings[buildingID].widthOrHeight; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)( + buildingSizeTileIndex, widthOrHeight); + int tileUnk = DAT_ViewportRenderState::instance.translationMatrix[this->buildingY + buildingY].addXgetTile + + this->buildingX + buildingX; + this->MiscDisplayLayer[tileUnk] &= ~0xc; + if (param_2 == 1) { + MACRO_CALL_MEMBER( + OpenSHC::Map::Entities::EntityState_Func::destroyEntitiesOnTile, DAT_EntityState::ptr)(tileUnk); + } + buildingSizeTileIndex++; + } while (buildingSizeTileIndex < this->constructionTileCount); + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/clearBuildingFootprintAndRemoveSiegeTower.cpp b/src/OpenSHC/Map/TileMapState/clearBuildingFootprintAndRemoveSiegeTower.cpp new file mode 100644 index 0000000000..d95c662d78 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/clearBuildingFootprintAndRemoveSiegeTower.cpp @@ -0,0 +1,56 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" +#include "OpenSHC/Map/Units/States/UnitState.hpp" +#include "OpenSHC/Map/Units/UnitType.hpp" + +#include "OpenSHC/Globals/DAT_PathFindingState.hpp" +#include "OpenSHC/Globals/DAT_UnitsState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_BUILDING; + using OpenSHC::Map::LogicHelpers::L_CRENEL; + using OpenSHC::Map::LogicHelpers::L_CRENEL_VARIATIONUnk; + using OpenSHC::Map::LogicHelpers::L_KEEP_NON_MANOR_HOUSE; + using OpenSHC::Map::LogicHelpers::L_STAIRS; + using OpenSHC::Map::LogicHelpers::L_WALL_OR_GATEHOUSE; + + using OpenSHC::Map::LogicHelpers::L_BUILDING; + using OpenSHC::Map::LogicHelpers::L_CRENEL; + using OpenSHC::Map::LogicHelpers::L_CRENEL_VARIATIONUnk; + using OpenSHC::Map::LogicHelpers::L_KEEP_NON_MANOR_HOUSE; + using OpenSHC::Map::LogicHelpers::L_STAIRS; + using OpenSHC::Map::LogicHelpers::L_WALL_OR_GATEHOUSE; + + using OpenSHC::Map::Units::UnitType; + using OpenSHC::Map::Units::States::UnitState; + + // FUNCTION: STRONGHOLDCRUSADER 0x004FAC70 + void TileMapState::clearBuildingFootprintAndRemoveSiegeTower(int x, int y, int size) + { + int tileIndex = 0; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)(tileIndex, size); + int tile = DAT_ViewportRenderState::instance.translationMatrix[this->buildingY + y].addXgetTile + + this->buildingX + x; + this->LogicLayer[tile] = this->LogicLayer[tile] + & ~(L_WALL_OR_GATEHOUSE | L_CRENEL | L_BUILDING | L_STAIRS | L_CRENEL_VARIATIONUnk + | L_KEEP_NON_MANOR_HOUSE); + this->BuildingLayer[tile] = 0; + this->HeightLayer[tile] = this->DefaultHeightLayer[tile]; + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::updatePathLinkagesInAllEightDirections, + DAT_PathFindingState::ptr)( + DAT_ViewportRenderState::instance.tileTranslationMatrix_YComponent[tile], tile); + short unitID = this->UnitLayer[tile]; + if (unitID != 0 && DAT_UnitsState::instance.units[unitID].unitType == OpenSHC::Map::Units::UT_S_TOWER) { + DAT_UnitsState::instance.units[unitID].state.generic = OpenSHC::Map::Units::States::US_DISAPPEAR; + } + tileIndex++; + } while (tileIndex < this->constructionTileCount); + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/clearBuildingFootprintAndResetUnits.cpp b/src/OpenSHC/Map/TileMapState/clearBuildingFootprintAndResetUnits.cpp new file mode 100644 index 0000000000..4839fc86ff --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/clearBuildingFootprintAndResetUnits.cpp @@ -0,0 +1,59 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_UnitsState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_BUILDING; + using OpenSHC::Map::LogicHelpers::L_CRENEL; + using OpenSHC::Map::LogicHelpers::L_CRENEL_VARIATIONUnk; + using OpenSHC::Map::LogicHelpers::L_KEEP_NON_MANOR_HOUSE; + using OpenSHC::Map::LogicHelpers::L_STAIRS; + using OpenSHC::Map::LogicHelpers::L_WALL_OR_GATEHOUSE; + + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x004FAB70 + void TileMapState::clearBuildingFootprintAndResetUnits(int x, int y, int size) + { + int buildingSizeTileIndex = 0; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)( + buildingSizeTileIndex, size); + int tile = DAT_ViewportRenderState::instance.translationMatrix[this->buildingY + y].addXgetTile + + this->buildingX + x; + this->LogicLayer[tile] = this->LogicLayer[tile] + & ~(L_WALL_OR_GATEHOUSE | L_CRENEL | L_BUILDING | L_STAIRS | L_CRENEL_VARIATIONUnk + | L_KEEP_NON_MANOR_HOUSE); + if ((this->MiscDisplayLayer[tile] & 0x20) != 0) { + this->MiscDisplayLayer[tile] = this->MiscDisplayLayer[tile] & 0xffdf; + this->HeightLayer[tile] = this->DefaultHeightLayer[tile]; + } + int buildingID = this->BuildingLayer[tile]; + this->BuildingLayer[tile] = 0; + if (DAT_BuildingsState::instance.buildings[buildingID].noRubble == 0) { + this->BuildingWasLayer[tile] = 0; + } else if (MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::isFootprintIndexOnEdge, this)( + buildingSizeTileIndex, size) + == FALSE) { + this->MiscDisplayLayer[tile] = this->MiscDisplayLayer[tile] | 0x4000; + } else { + this->MiscDisplayLayer[tile] = this->MiscDisplayLayer[tile] | 0x2000; + } + for (short unitID = this->UnitLayer[tile]; unitID != 0; + unitID = DAT_UnitsState::instance.units[unitID].nextUnitOnTheSameTile) { + DAT_UnitsState::instance.units[unitID].vanish = 0; + DAT_UnitsState::instance.units[unitID].unknownCountdown_0x402 = 0; + } + buildingSizeTileIndex++; + this->ChangedLayer[tile] = 2; + } while (buildingSizeTileIndex < this->constructionTileCount); + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/clearBuildingFootprintWithEdgeRubble.cpp b/src/OpenSHC/Map/TileMapState/clearBuildingFootprintWithEdgeRubble.cpp new file mode 100644 index 0000000000..0f215a9176 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/clearBuildingFootprintWithEdgeRubble.cpp @@ -0,0 +1,53 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_BUILDING; + using OpenSHC::Map::LogicHelpers::L_CRENEL; + using OpenSHC::Map::LogicHelpers::L_CRENEL_VARIATIONUnk; + using OpenSHC::Map::LogicHelpers::L_KEEP_NON_MANOR_HOUSE; + using OpenSHC::Map::LogicHelpers::L_STAIRS; + using OpenSHC::Map::LogicHelpers::L_WALL_OR_GATEHOUSE; + + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x004FAD70 + void TileMapState::clearBuildingFootprintWithEdgeRubble(int x, int y, int size) + { + int buildingSizeTileIndex = 0; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)( + buildingSizeTileIndex, size); + int tile = DAT_ViewportRenderState::instance.translationMatrix[this->buildingY + y].addXgetTile + + this->buildingX + x; + this->LogicLayer[tile] = this->LogicLayer[tile] + & ~(L_WALL_OR_GATEHOUSE | L_CRENEL | L_BUILDING | L_STAIRS | L_CRENEL_VARIATIONUnk + | L_KEEP_NON_MANOR_HOUSE); + if ((this->MiscDisplayLayer[tile] & 0x20) != 0) { + this->MiscDisplayLayer[tile] = this->MiscDisplayLayer[tile] & 0xffdf; + this->HeightLayer[tile] = this->DefaultHeightLayer[tile]; + } + short buildingID = this->BuildingLayer[tile]; + this->BuildingLayer[tile] = 0; + if (DAT_BuildingsState::instance.buildings[buildingID].noRubble == 0) { + this->BuildingWasLayer[tile] = 0; + } else if (MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::isFootprintIndexOnEdge, this)( + buildingSizeTileIndex, size) + == FALSE) { + this->MiscDisplayLayer[tile] = this->MiscDisplayLayer[tile] | 0x4000; + } else { + this->MiscDisplayLayer[tile] = this->MiscDisplayLayer[tile] | 0x2000; + } + buildingSizeTileIndex++; + this->ChangedLayer[tile] = 2; + } while (buildingSizeTileIndex < this->constructionTileCount); + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/clearBuildingFromTerrain.cpp b/src/OpenSHC/Map/TileMapState/clearBuildingFromTerrain.cpp new file mode 100644 index 0000000000..75ae8065f2 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/clearBuildingFromTerrain.cpp @@ -0,0 +1,118 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" +#include "OpenSHC/UI/MinimapViewState.func.hpp" +#include "OpenSHC/Map/Buildings/BuildingType.hpp" +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_MinimapViewState.hpp" +#include "OpenSHC/Globals/DAT_PathFindingState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::Buildings::BuildingType; + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x00515A20 + void TileMapState::clearBuildingFromTerrain(int buildingID) + { + uint y = (short)DAT_BuildingsState::instance.buildings[buildingID].y; + uint size = DAT_BuildingsState::instance.buildings[buildingID].widthOrHeight; + uint x = (short)DAT_BuildingsState::instance.buildings[buildingID].x; + if (DAT_BuildingsState::instance.buildings[buildingID].buildingType != OpenSHC::Map::Buildings::BT_KILLINGPIT) { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::validateBuildingPlacementAtTile, this)( + DAT_BuildingsState::instance.buildings[buildingID].owner, x, y); + if (this->buildingPlacementFail != FALSE) { + return; + } + } + + if (DAT_BuildingsState::instance.buildings[buildingID].buildingType == OpenSHC::Map::Buildings::BT_STOCKPILE) { + if (DAT_BuildingsState::instance.buildings[buildingID].field125_0x190 == 1) { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::clearStockpileFootprintTiles, this)(x, y); + } + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::clearFixedSizeTwoBuildingFootprint, this)(x, y); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::updateAreaBasedOnSurrounding, this)(x, y, size); + } else if (DAT_BuildingsState::instance.buildings[buildingID].buildingType + == OpenSHC::Map::Buildings::BT_WHEATFARM + || DAT_BuildingsState::instance.buildings[buildingID].buildingType == OpenSHC::Map::Buildings::BT_HOPFARM) { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::clearBuildingFootprintAndResetUnits, this)(x, y, size); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::clearBuildingDisplayFlagsAndEntities, this)( + buildingID, 1); + int surfaceArea; + if (DAT_BuildingsState::instance.buildings[buildingID].buildingType + == OpenSHC::Map::Buildings::BT_WHEATFARM) { + surfaceArea = 36; + } else { + surfaceArea = 24; + } + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::clearBuildingTilesAndTrees, this)( + buildingID, surfaceArea); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::unmarkBuildingFootprintFlag, this)(x, y, 9); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::updateAreaBasedOnSurrounding, this)(x, y, 9); + size = 6; + } else if (DAT_BuildingsState::instance.buildings[buildingID].buildingType + == OpenSHC::Map::Buildings::BT_DAIRYFARM) { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::clearBuildingFootprintAndResetUnits, this)(x, y, size); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::clearBuildingDisplayFlagsAndEntities, this)( + buildingID, 1); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::clearBuildingTilesAndTrees, this)(buildingID, 0x1b); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::unmarkBuildingFootprintFlag, this)(x, y, 10); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::updateAreaBasedOnSurrounding, this)(x, y, 10); + size = 6; + } else if (DAT_BuildingsState::instance.buildings[buildingID].buildingType + == OpenSHC::Map::Buildings::BT_APPLEFARM) { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::clearBuildingFootprintAndResetUnits, this)(x, y, size); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::clearBuildingDisplayFlagsAndEntities, this)( + buildingID, 1); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::clearBuildingTilesAndTrees, this)(buildingID, 8); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::unmarkBuildingFootprintFlag, this)(x, y, 0xb); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::updateAreaBasedOnSurrounding, this)(x, y, 0xb); + size = 6; + } else { + if (DAT_BuildingsState::instance.buildings[buildingID].buildingType + == OpenSHC::Map::Buildings::BT_DRAWBRIDGE) { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::clearSizeFiveBuildingFootprintAndMoats, this)(x, y); + } else if (DAT_BuildingsState::instance.buildings[buildingID].buildingType + == OpenSHC::Map::Buildings::BT_CATAPULT + || DAT_BuildingsState::instance.buildings[buildingID].buildingType + == OpenSHC::Map::Buildings::BT_TREBUCHET + || DAT_BuildingsState::instance.buildings[buildingID].buildingType + == OpenSHC::Map::Buildings::BT_BATTERINGRAM + || DAT_BuildingsState::instance.buildings[buildingID].buildingType + == OpenSHC::Map::Buildings::BT_SIEGETOWER + || DAT_BuildingsState::instance.buildings[buildingID].buildingType == OpenSHC::Map::Buildings::BT_SHIELD + || DAT_BuildingsState::instance.buildings[buildingID].buildingType + == OpenSHC::Map::Buildings::BT_FIREBALLISTA) { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::clearBuildingFootprintWithEdgeRubble, this)( + x, y, size); + } else if (DAT_BuildingsState::instance.buildings[buildingID].buildingType + == OpenSHC::Map::Buildings::BT_SIEGETOWER_PLACED) { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::clearBuildingFootprintAndRemoveSiegeTower, this)( + x, y, size); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::clearBuildingFootprintAndResetUnits, this)( + x, y, size); + } else { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::clearBuildingFootprintAndResetUnits, this)( + x, y, size); + } + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::clearBuildingDisplayFlagsAndEntities, this)( + buildingID, 1); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::updateAreaBasedOnSurrounding, this)(x, y, size); + } + + if (DAT_BuildingsState::instance.buildings[buildingID].buildingType + != OpenSHC::Map::Buildings::BT_SIEGETOWER_PLACED) { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::updatePathLinkagesForBuilding, this)(buildingID); + } + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::updateWalkAndPathLayer, + DAT_PathFindingState::ptr)(size + 6, x, y); + DAT_PathFindingState::instance.toggleUpdateSeparateAreaTileMap = 1; + this->field204_0x554a30 = 1; + MACRO_CALL_MEMBER(OpenSHC::UI::MinimapViewState_Func::triggerMinimapRedraw, DAT_MinimapViewState::ptr)(1); + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/clearBuildingTilesAndTrees.cpp b/src/OpenSHC/Map/TileMapState/clearBuildingTilesAndTrees.cpp new file mode 100644 index 0000000000..8287496ae6 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/clearBuildingTilesAndTrees.cpp @@ -0,0 +1,49 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Map/LandscapeState.func.hpp" +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" +#include "OpenSHC/Map/LogicHelpers/Logic1.hpp" + +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_LandscapeState.hpp" +#include "OpenSHC/Globals/DAT_PathFindingState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + using namespace OpenSHC::Map::LogicHelpers; // L_* flags + using OpenSHC::Map::Buildings::Building; + + using OpenSHC::Map::LogicHelpers::L_BUILDING; + using OpenSHC::Map::LogicHelpers::L_FARM_FIELD_APPLE; + using OpenSHC::Map::LogicHelpers::L_FARM_FIELD_DAIRY; + using OpenSHC::Map::LogicHelpers::L_FARM_FIELD_HOP; + using OpenSHC::Map::LogicHelpers::L_FARM_FIELD_WHEAT; + + // FUNCTION: STRONGHOLDCRUSADER 0x004FAAB0 + void TileMapState::clearBuildingTilesAndTrees(int buildingID, int surfaceArea) + { + for (int i = 0; i < surfaceArea; i++) { + int tileUnk = DAT_BuildingsState::instance.buildings[buildingID].tileRefs[i]; + if ((this->LogicLayer[tileUnk] & L_FARM_FIELD_APPLE) != 0) { + int treeID = this->OrganismLayer[tileUnk]; + if (treeID != 0 && treeID < 2000) { + MACRO_CALL_MEMBER(OpenSHC::Map::LandscapeState_Func::removeTree, DAT_LandscapeState::ptr)(treeID); + } + } + this->LogicLayer[tileUnk] = this->LogicLayer[tileUnk] + & ~(L_BUILDING | L_FARM_FIELD_WHEAT | L_FARM_FIELD_HOP | L_FARM_FIELD_APPLE | L_FARM_FIELD_DAIRY); + this->DamageLayer[tileUnk] = 0; + this->BuildingLayer[tileUnk] = 0; + if (DAT_BuildingsState::instance.buildings[buildingID].noRubble == 0) { + this->BuildingWasLayer[tileUnk] = 0; + } + this->ChangedLayer[tileUnk] = 2; + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::updatePathLinkagesInAllEightDirections, + DAT_PathFindingState::ptr)( + (int)DAT_ViewportRenderState::instance.tileTranslationMatrix_YComponent[tileUnk], tileUnk); + } + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/clearDrawBridgeWater.cpp b/src/OpenSHC/Map/TileMapState/clearDrawBridgeWater.cpp new file mode 100644 index 0000000000..4f2356f8d3 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/clearDrawBridgeWater.cpp @@ -0,0 +1,35 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_MOAT; + + // FUNCTION: STRONGHOLDCRUSADER 0x00508870 + void TileMapState::clearDrawBridgeWater(int x, int y) + { + int buildingSizeTileIndex = 0; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)( + buildingSizeTileIndex, 5); + int targetedTile = DAT_ViewportRenderState::instance.translationMatrix[this->buildingY + y].addXgetTile + + this->buildingX + x; + this->LogicLayer[targetedTile] = this->LogicLayer[targetedTile] & ~L_MOAT; + this->HeightLayer[targetedTile] = 8; + uint moatID = MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::returnOwnedMoatAtTile, this)(targetedTile); + if (moatID != 0) { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::clearMoatData, this)(moatID); + this->LogicLayer[targetedTile] = this->LogicLayer[targetedTile] & ~L_MOAT; + this->BuildingWasLayer[targetedTile] = 0; + } + this->BuildingLayer[targetedTile] = 0; + buildingSizeTileIndex++; + this->BuildingWasLayer[targetedTile] = 0; + this->ChangedLayer[targetedTile] = 2; + } while (buildingSizeTileIndex < this->constructionTileCount); + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/clearFixedSizeTwoBuildingFootprint.cpp b/src/OpenSHC/Map/TileMapState/clearFixedSizeTwoBuildingFootprint.cpp new file mode 100644 index 0000000000..83bda1493f --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/clearFixedSizeTwoBuildingFootprint.cpp @@ -0,0 +1,42 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_BUILDING; + using OpenSHC::Map::LogicHelpers::L_CRENEL; + using OpenSHC::Map::LogicHelpers::L_CRENEL_VARIATIONUnk; + using OpenSHC::Map::LogicHelpers::L_KEEP_NON_MANOR_HOUSE; + using OpenSHC::Map::LogicHelpers::L_STAIRS; + using OpenSHC::Map::LogicHelpers::L_STOCKPILEUnk; + using OpenSHC::Map::LogicHelpers::L_WALL_OR_GATEHOUSE; + + // FUNCTION: STRONGHOLDCRUSADER 0x004FAE50 + void TileMapState::clearFixedSizeTwoBuildingFootprint(int x, int y) + { + int buildingSizeTileIndex = 0; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)( + buildingSizeTileIndex, 2); + int tile = DAT_ViewportRenderState::instance.translationMatrix[this->buildingY + y].addXgetTile + + this->buildingX + x; + this->LogicLayer[tile] = this->LogicLayer[tile] + & ~(L_STOCKPILEUnk | L_WALL_OR_GATEHOUSE | L_CRENEL | L_BUILDING | L_STAIRS | L_CRENEL_VARIATIONUnk + | L_KEEP_NON_MANOR_HOUSE); + int buildingID = this->BuildingLayer[tile]; + this->BuildingLayer[tile] = 0; + if (DAT_BuildingsState::instance.buildings[buildingID].noRubble == 0) { + this->BuildingWasLayer[tile] = 0; + } else { + this->MiscDisplayLayer[tile] = this->MiscDisplayLayer[tile] | 0x4000; + } + buildingSizeTileIndex++; + this->HeightLayer[tile] = this->DefaultHeightLayer[tile]; + } while (buildingSizeTileIndex < this->constructionTileCount); + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/clearInvalidMoatEntries.cpp b/src/OpenSHC/Map/TileMapState/clearInvalidMoatEntries.cpp new file mode 100644 index 0000000000..9387b69c7f --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/clearInvalidMoatEntries.cpp @@ -0,0 +1,30 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Globals/DAT_TileMapState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_MOAT; + using OpenSHC::Map::LogicHelpers::L_MOAT_DUG_OR_PLANNED; + + // FUNCTION: STRONGHOLDCRUSADER 0x005006C0 + void TileMapState::clearInvalidMoatEntries() + { + for (int moatID = 1; moatID < this->currentMoatCount; moatID++) { + if (this->moats[moatID].owner == 0) { + continue; + } + int tile = this->moats[moatID].tile; + if ((DAT_TileMapState::instance.LogicLayer[tile] & (L_MOAT_DUG_OR_PLANNED | L_MOAT)) != 0) { + continue; + } + if (this->BuildingLayer[tile] != 0) { + continue; + } + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::clearMoatData, this)(moatID); + } + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/clearMoat.cpp b/src/OpenSHC/Map/TileMapState/clearMoat.cpp new file mode 100644 index 0000000000..e2d8ae0c07 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/clearMoat.cpp @@ -0,0 +1,26 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_MOAT_DUG_OR_PLANNED; + + // FUNCTION: STRONGHOLDCRUSADER 0x005005F0 + void TileMapState::clearMoat(int tile) + { + if ((this->LogicLayer[tile] & L_MOAT_DUG_OR_PLANNED) == 0) { + return; + } + + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::clearMoatDataAtTile, this)(tile + - DAT_ViewportRenderState::instance + .translationMatrix[DAT_ViewportRenderState::instance.tileTranslationMatrix_YComponent[tile]] + .addXgetTile, + DAT_ViewportRenderState::instance.tileTranslationMatrix_YComponent[tile]); + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_MOAT_DUG_OR_PLANNED; + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/clearMoatDataAtTile.cpp b/src/OpenSHC/Map/TileMapState/clearMoatDataAtTile.cpp new file mode 100644 index 0000000000..79c5839089 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/clearMoatDataAtTile.cpp @@ -0,0 +1,23 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/IO/LowLevelMemory.func.hpp" + +#include "OpenSHC/Globals/DAT_LowLevelMemory.hpp" + +namespace OpenSHC { +namespace Map { + + // FUNCTION: STRONGHOLDCRUSADER 0x00500310 + void TileMapState::clearMoatDataAtTile(int x, int y) + { + for (int moatID = 0; moatID < this->currentMoatCount; moatID++) { + if (this->moats[moatID].x == x && this->moats[moatID].y == y) { + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + sizeof(Moat), 0, &this->moats[moatID]); + this->moatTileCount = this->moatTileCount - 1; + } + } + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/clearRockFootprintFlags.cpp b/src/OpenSHC/Map/TileMapState/clearRockFootprintFlags.cpp new file mode 100644 index 0000000000..1dd0646459 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/clearRockFootprintFlags.cpp @@ -0,0 +1,29 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Globals/DAT_LandscapeState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_ROCKY; + + // FUNCTION: STRONGHOLDCRUSADER 0x004FB970 + void TileMapState::clearRockFootprintFlags(int rockID) + { + int rockX = (short)DAT_LandscapeState::instance.rocks[rockID].x; + int rockY = (short)DAT_LandscapeState::instance.rocks[rockID].y; + int buildingSizeTileIndex = 0; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)( + buildingSizeTileIndex, DAT_LandscapeState::instance.rocks[rockID].size); + buildingSizeTileIndex++; + int tile = DAT_ViewportRenderState::instance.translationMatrix[this->buildingY + rockY].addXgetTile + rockX + + this->buildingX; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_ROCKY; + this->OrganismLayer[tile] = 0; + } while (buildingSizeTileIndex < this->constructionTileCount); + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/clearSizeFiveBuildingFootprintAndMoats.cpp b/src/OpenSHC/Map/TileMapState/clearSizeFiveBuildingFootprintAndMoats.cpp new file mode 100644 index 0000000000..0437bd372e --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/clearSizeFiveBuildingFootprintAndMoats.cpp @@ -0,0 +1,53 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L2_EARTH_AND_STONES; + using OpenSHC::Map::LogicHelpers::L_BUILDING; + using OpenSHC::Map::LogicHelpers::L_MOAT; + + // FUNCTION: STRONGHOLDCRUSADER 0x00508760 + void TileMapState::clearSizeFiveBuildingFootprintAndMoats(int x, int y) + { + int buildingSizeTileIndex = 0; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)( + buildingSizeTileIndex, 5); + int targetedTile = DAT_ViewportRenderState::instance.translationMatrix[this->buildingY + y].addXgetTile + + this->buildingX + x; + int buildingID = this->BuildingLayer[targetedTile]; + int variation = DAT_BuildingsState::instance.buildings[buildingID].buildingVariation; + this->LogicLayer[targetedTile] = this->LogicLayer[targetedTile] & ~L_BUILDING; + if (DAT_TerrainDefinedData::instance.DrawbridgeOrientationMapping[variation / 2][buildingSizeTileIndex] + != 0) { + uint moatID + = MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::returnOwnedMoatAtTile, this)(targetedTile); + if (moatID != 0) { + if (DAT_BuildingsState::instance.buildings[buildingID].noRubble == 0) { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::clearMoatData, this)(moatID); + this->LogicLayer[targetedTile] = this->LogicLayer[targetedTile] & ~L_MOAT; + this->Logic2Layer[targetedTile] = this->Logic2Layer[targetedTile] | L2_EARTH_AND_STONES; + this->BuildingWasLayer[targetedTile] = 0; + this->HeightLayer[targetedTile] = 8; + } else { + this->LogicLayer[targetedTile] = this->LogicLayer[targetedTile] | L_MOAT; + } + } + } + if ((this->LogicLayer[targetedTile] & L_MOAT) == 0) { + this->Logic2Layer[targetedTile] = this->Logic2Layer[targetedTile] | L2_EARTH_AND_STONES; + this->BuildingWasLayer[targetedTile] = 0; + } + this->BuildingLayer[targetedTile] = 0; + buildingSizeTileIndex++; + this->ChangedLayer[targetedTile] = 2; + } while (buildingSizeTileIndex < this->constructionTileCount); + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/clearStockpileFootprintTiles.cpp b/src/OpenSHC/Map/TileMapState/clearStockpileFootprintTiles.cpp new file mode 100644 index 0000000000..3e09ad2a99 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/clearStockpileFootprintTiles.cpp @@ -0,0 +1,58 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_STOCKPILEUnk; + using OpenSHC::Map::LogicHelpers::L_WALL_OR_GATEHOUSE; + + // FUNCTION: STRONGHOLDCRUSADER 0x004FAF70 + void TileMapState::clearStockpileFootprintTiles(int x, int y) + { + int tile; + for (int offset = 0; offset < 9; offset += 3) { + tile = DAT_ViewportRenderState::instance + .translationMatrix[DAT_TerrainDefinedData::instance.StockpilePathableOffsets[offset + 0].y + y] + .addXgetTile + + x + DAT_TerrainDefinedData::instance.StockpilePathableOffsets[offset + 0].x; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~(L_STOCKPILEUnk | L_WALL_OR_GATEHOUSE); + this->HeightLayer[tile] = this->DefaultHeightLayer[tile]; + if (DAT_BuildingsState::instance.buildings[this->AlphaGFXLayer[tile]].noRubble == 0) { + this->BuildingWasLayer[tile] = 0; + } else { + this->MiscDisplayLayer[tile] = this->MiscDisplayLayer[tile] | 0x4000; + } + this->AlphaGFXLayer[tile] = 0; + tile = DAT_ViewportRenderState::instance + .translationMatrix[DAT_TerrainDefinedData::instance.StockpilePathableOffsets[offset + 1].y + y] + .addXgetTile + + x + DAT_TerrainDefinedData::instance.StockpilePathableOffsets[offset + 1].x; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~(L_STOCKPILEUnk | L_WALL_OR_GATEHOUSE); + this->HeightLayer[tile] = this->DefaultHeightLayer[tile]; + if (DAT_BuildingsState::instance.buildings[this->AlphaGFXLayer[tile]].noRubble == 0) { + this->BuildingWasLayer[tile] = 0; + } else { + this->MiscDisplayLayer[tile] = this->MiscDisplayLayer[tile] | 0x4000; + } + this->AlphaGFXLayer[tile] = 0; + tile = DAT_ViewportRenderState::instance + .translationMatrix[DAT_TerrainDefinedData::instance.StockpilePathableOffsets[offset + 2].y + y] + .addXgetTile + + x + DAT_TerrainDefinedData::instance.StockpilePathableOffsets[offset + 2].x; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~(L_STOCKPILEUnk | L_WALL_OR_GATEHOUSE); + this->HeightLayer[tile] = this->DefaultHeightLayer[tile]; + if (DAT_BuildingsState::instance.buildings[this->AlphaGFXLayer[tile]].noRubble == 0) { + this->BuildingWasLayer[tile] = 0; + } else { + this->MiscDisplayLayer[tile] = this->MiscDisplayLayer[tile] | 0x4000; + } + this->AlphaGFXLayer[tile] = 0; + } + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/clearTreeFootprintFlags.cpp b/src/OpenSHC/Map/TileMapState/clearTreeFootprintFlags.cpp new file mode 100644 index 0000000000..846a531997 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/clearTreeFootprintFlags.cpp @@ -0,0 +1,32 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Globals/DAT_LandscapeState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_TREE; + using OpenSHC::Map::LogicHelpers::L_TREE_VARIATION; + + // FUNCTION: STRONGHOLDCRUSADER 0x004FB8E0 + void TileMapState::clearTreeFootprintFlags(int treeID) + { + int treeX = (short)DAT_LandscapeState::instance.trees[treeID].xPosition; + int treeY = (short)DAT_LandscapeState::instance.trees[treeID].yPosition; + this->OrganismLayer[DAT_LandscapeState::instance.trees[treeID].tile] = 0; + this->LogicLayer[DAT_LandscapeState::instance.trees[treeID].tile] + = this->LogicLayer[DAT_LandscapeState::instance.trees[treeID].tile] & ~L_TREE; + int index = 0; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)( + index, DAT_LandscapeState::instance.trees[treeID].size); + index++; + int tile = DAT_ViewportRenderState::instance.translationMatrix[this->buildingY + treeY].addXgetTile + + this->buildingX + treeX; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_TREE_VARIATION; + } while (index < this->constructionTileCount); + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/collectCliffEdgeTilesForClimbData.cpp b/src/OpenSHC/Map/TileMapState/collectCliffEdgeTilesForClimbData.cpp new file mode 100644 index 0000000000..ed5ca76cd9 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/collectCliffEdgeTilesForClimbData.cpp @@ -0,0 +1,61 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Globals/DAT_ClimbLogicDefinedData.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L2_OASIS_GRASS; + using OpenSHC::Map::LogicHelpers::L2_PLATEAU_HIGH; + using OpenSHC::Map::LogicHelpers::L2_STONES_OR_DRIVEN_SANDUnk; + using OpenSHC::Map::LogicHelpers::L_BORDER; + using OpenSHC::Map::LogicHelpers::L_BORDER_EDGE; + using OpenSHC::Map::LogicHelpers::L_RIVER; + using OpenSHC::Map::LogicHelpers::L_SEA; + + // FUNCTION: STRONGHOLDCRUSADER 0x004FC340 + void TileMapState::collectCliffEdgeTilesForClimbData() + { + this->temporaryTerrainTypeIndex = 0; + for (int tile = 0; tile < 80400; tile++) { + if ((this->LogicLayer[tile] & (L_BORDER | L_BORDER_EDGE)) != 0) { + continue; + } + + if ((this->LogicLayer[tile] & L_RIVER) != 0 + && (this->Logic2Layer[tile] & L2_STONES_OR_DRIVEN_SANDUnk) != 0) { + this->temporaryTerrainTypeBinaryArray[this->temporaryTerrainTypeIndex] = 1; + this->temporaryTerrainTypeArray[this->temporaryTerrainTypeIndex] = tile; + for (int index = 0; index < 8; index++) { + int neighbour + = this->directionTranslationMatrix[DAT_ViewportRenderState::instance + .tileTranslationMatrix_YComponent[tile]] + [DAT_ClimbLogicDefinedData::instance.field5_0x2c[index]] + + tile; + if ((this->LogicLayer[neighbour] & L_RIVER) != 0 + && this->HeightLayer[tile] + 0x50 < (uint)this->HeightLayer[neighbour]) { + this->temporaryTerrainTypeBinaryArray[this->temporaryTerrainTypeIndex] = 0; + break; + } + } + this->temporaryTerrainTypeIndex = this->temporaryTerrainTypeIndex + 1; + if ((int)this->temporaryTerrainTypeIndex > 999) { + return; + } + } + + if (((this->LogicLayer[tile] & L_RIVER) != 0 && (this->Logic2Layer[tile] & L2_OASIS_GRASS) != 0) + || ((this->LogicLayer[tile] & L_SEA) != 0 && (this->Logic2Layer[tile] & L2_PLATEAU_HIGH) != 0)) { + this->temporaryTerrainTypeBinaryArray[this->temporaryTerrainTypeIndex] = 1; + this->temporaryTerrainTypeArray[this->temporaryTerrainTypeIndex] = tile; + this->temporaryTerrainTypeIndex = this->temporaryTerrainTypeIndex + 1; + if ((int)this->temporaryTerrainTypeIndex > 999) { + return; + } + } + } + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/computeClimbRampRotation.cpp b/src/OpenSHC/Map/TileMapState/computeClimbRampRotation.cpp new file mode 100644 index 0000000000..4eaad9373e --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/computeClimbRampRotation.cpp @@ -0,0 +1,90 @@ +#include "../TileMapState.func.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_WALL_OR_GATEHOUSE; + + // FUNCTION: STRONGHOLDCRUSADER 0x004FC810 + int TileMapState::computeClimbRampRotation(int tileUnk, uint x, uint y) + { + int high; + if ((this->LogicLayer[tileUnk] & L_WALL_OR_GATEHOUSE) != 0) { + high = this->DefaultHeightLayer[tileUnk]; + } else { + high = this->HeightLayer[tileUnk]; + } + + int neighbour = this->directionTranslationMatrix[y][this->screenSouthDirection] + tileUnk; + int heightAt86; + if ((this->LogicLayer[neighbour] & L_WALL_OR_GATEHOUSE) != 0) { + heightAt86 = this->DefaultHeightLayer[neighbour]; + } else { + heightAt86 = this->HeightLayer[neighbour]; + } + + neighbour = this->directionTranslationMatrix[y][this->screenEastDirection] + tileUnk; + int heightAt85; + if ((this->LogicLayer[neighbour] & L_WALL_OR_GATEHOUSE) != 0) { + heightAt85 = this->DefaultHeightLayer[neighbour]; + } else { + heightAt85 = this->HeightLayer[neighbour]; + } + + neighbour = this->directionTranslationMatrix[y][this->screenSouthEastDirection] + tileUnk; + int heightAt84; + if ((this->LogicLayer[neighbour] & L_WALL_OR_GATEHOUSE) != 0) { + heightAt84 = this->DefaultHeightLayer[neighbour]; + } else { + heightAt84 = this->HeightLayer[neighbour]; + } + + uint rotation; + if (high > heightAt86 + 0x14 && heightAt86 < 0x88) { + if (high > heightAt85 + 0x14 && heightAt85 < 0x88) { + if (high > heightAt84 + 0x14 && heightAt84 < 0x88) { + rotation = 5; + } else { + rotation = 3; + } + } else { + rotation = 1; + } + } else if (high > heightAt85 + 0x14 && heightAt85 < 0x88) { + if (high > heightAt86 + 0x14 && heightAt86 < 0x88) { + rotation = 3; + } else { + rotation = 2; + } + } else if (heightAt86 < 0x88 || heightAt85 < 0x88) { + /* 0 when the tileUnk is not high enough above its neighbour, 5 when it is */ + rotation = (high <= heightAt84 + 0x14) - 1 & 5; + } else { + rotation = 4; + } + + if (this->mapOrientation == 0) { + if (rotation == 1) { + this->wallCornerRotation = 0x20 - (x & 0x1f); + } else { + this->wallCornerRotation = 0x20 - (y & 0x1f); + } + } else if (this->mapOrientation == 4) { + if (rotation == 1) { + this->wallCornerRotation = (x & 0x1f) + 1; + } else { + this->wallCornerRotation = (y & 0x1f) + 1; + } + } else if (this->mapOrientation == 2) { + this->wallCornerRotation = (y & 0x1f) + 1; + } else { + this->wallCornerRotation = 0x20 - (y & 0x1f); + } + if ((int)this->wallCornerRotation > 0x1f) { + this->wallCornerRotation = 1; + } + return rotation; + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/computeTileAlongAxisOffset.cpp b/src/OpenSHC/Map/TileMapState/computeTileAlongAxisOffset.cpp new file mode 100644 index 0000000000..13da71bbac --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/computeTileAlongAxisOffset.cpp @@ -0,0 +1,28 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + + // FUNCTION: STRONGHOLDCRUSADER 0x00500B50 + int TileMapState::computeTileAlongAxisOffset(int tileUnk, int addend, uint offset) + { + int yStep = 1; + int direction = 4; + if ((int)offset < 0) { + yStep = -1; + direction = 0; + } + + int y = DAT_ViewportRenderState::instance.tileTranslationMatrix_YComponent[tileUnk]; + int count = abs((int)offset); + for (int i = 0; i < count; i++) { + tileUnk = tileUnk + this->directionTranslationMatrix[y][direction]; + y = y + yStep; + } + return tileUnk + addend; + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/computeTileCliffEdgeFlags.cpp b/src/OpenSHC/Map/TileMapState/computeTileCliffEdgeFlags.cpp new file mode 100644 index 0000000000..121cb5befd --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/computeTileCliffEdgeFlags.cpp @@ -0,0 +1,98 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Game/GameMode.hpp" + +#include "OpenSHC/Globals/DAT_GameSynchronyState.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_RIVER; + + using OpenSHC::Game::GameMode; + + // FUNCTION: STRONGHOLDCRUSADER 0x004FC0B0 + void TileMapState::computeTileCliffEdgeFlags(int tileUnk, int x, int y) + { + int high = this->HeightLayer[tileUnk]; + int lowest = high; + int highest = high; + if (DAT_GameSynchronyState::instance.currentGameMode == OpenSHC::Game::GM_MULTIPLAYER) { + return; + } + + /* the high of each of the eight neighbours, or the own high where there is no river */ + int heights[8]; + for (int i = 0; i < 8; i++) { + uint neighbourY = y + DAT_TerrainDefinedData::instance.field2345_0x372c[i].y; + uint neighbourX = x + DAT_TerrainDefinedData::instance.field2345_0x372c[i].x; + heights[i] = high; + if (neighbourX <= 399 && neighbourY <= 399 + && DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[neighbourY * 400 + neighbourX] != 0) { + int neighbour = DAT_ViewportRenderState::instance.translationMatrix[neighbourY].addXgetTile + + DAT_TerrainDefinedData::instance.field2345_0x372c[i].x + x; + if ((this->LogicLayer[neighbour] & L_RIVER) != 0) { + heights[i] = this->HeightLayer[neighbour]; + if (heights[i] < lowest) { + lowest = heights[i]; + } else if (heights[i] > highest) { + highest = heights[i]; + } + } + } + } + + this->Logic2Layer[tileUnk] + = this->Logic2Layer[tileUnk] & (OpenSHC::Map::LogicHelpers::L2_BEACH | OpenSHC::Map::LogicHelpers::L2_OASIS_GRASS | OpenSHC::Map::LogicHelpers::L2_PLATEAU_HIGH); + byte flags = this->Logic2Layer[tileUnk]; + if (lowest < high) { + /* the bank runs along whichever axis the map is turned to */ + if (this->mapOrientation == 0) { + if (heights[2] < high && heights[4] < high) { + this->Logic2Layer[tileUnk] = flags | 1; + } else if (heights[4] < high) { + this->Logic2Layer[tileUnk] = flags | 2; + } else if (heights[2] < high) { + this->Logic2Layer[tileUnk] = flags | 4; + } + } else if (this->mapOrientation == 4) { + if (heights[0] < high) { + if (heights[6] < high) { + this->Logic2Layer[tileUnk] = flags | 1; + } else { + this->Logic2Layer[tileUnk] = flags | 2; + } + } else if (heights[6] < high) { + this->Logic2Layer[tileUnk] = flags | 4; + } + } else if (this->mapOrientation == 2) { + if (heights[4] < high && heights[6] < high) { + this->Logic2Layer[tileUnk] = flags | 1; + } else if (heights[6] < high) { + this->Logic2Layer[tileUnk] = flags | 2; + } else if (heights[4] < high) { + this->Logic2Layer[tileUnk] = flags | 4; + } + } else if (this->mapOrientation == 6) { + if (heights[0] < high && heights[2] < high) { + this->Logic2Layer[tileUnk] = flags | 1; + } else if (heights[2] < high) { + this->Logic2Layer[tileUnk] = flags | 2; + } else if (heights[0] < high) { + this->Logic2Layer[tileUnk] = flags | 4; + } + } + } else if (highest > high) { + /* a bank all round: low step becomes a beach, a high one a cliff */ + if (highest > high + 0x10) { + this->Logic2Layer[tileUnk] = flags | 0x40; + } else { + this->Logic2Layer[tileUnk] = flags | 0x80; + } + } + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/computeTileLuminescence.cpp b/src/OpenSHC/Map/TileMapState/computeTileLuminescence.cpp new file mode 100644 index 0000000000..5b7e9f6cc3 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/computeTileLuminescence.cpp @@ -0,0 +1,290 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Map/Buildings/BuildingsState.func.hpp" +#include "OpenSHC/Map/LandscapeState.func.hpp" + +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_LandscapeState.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_BORDER; + using OpenSHC::Map::LogicHelpers::L_BORDER_EDGE; + using OpenSHC::Map::LogicHelpers::L_BUILDING; + using OpenSHC::Map::LogicHelpers::L_KEEP_NON_MANOR_HOUSE; + using OpenSHC::Map::LogicHelpers::L_MOAT; + using OpenSHC::Map::LogicHelpers::L_TREE; + using OpenSHC::Map::LogicHelpers::L_TREE_VARIATION; + + // FUNCTION: STRONGHOLDCRUSADER 0x004F7A80 + void TileMapState::computeTileLuminescence(int tileUnk, int y) + { + uint logic = this->LogicLayer[tileUnk]; + int shade = 2; + int alongShade = 2; + int acrossShade = 2; + int diagonal = 0; + int opposite = 0; + int along = 0; + int across = 0; + uint high = 0; + int slope = 0; + if ((logic & (L_BORDER | L_BORDER_EDGE | L_BUILDING | L_KEEP_NON_MANOR_HOUSE)) != 0) { + return; + } + + /* the light comes from one corner of the screen, so the rays turn with the map */ + switch (this->mapOrientation) { + case 0: + diagonal = 5; + opposite = 1; + along = 4; + across = 6; + break; + case 2: + diagonal = 7; + opposite = 3; + along = 6; + across = 0; + break; + case 4: + diagonal = 1; + opposite = 5; + along = 0; + across = 2; + break; + case 6: + diagonal = 3; + opposite = 7; + along = 2; + across = 4; + } + + uint ownHeight = this->HeightLayer[tileUnk]; + if ((logic & L_TREE) != 0) { + int stage = MACRO_CALL_MEMBER(OpenSHC::Map::LandscapeState_Func::getTreeGrowthTargetStage, DAT_LandscapeState::ptr)( + this->OrganismLayer[tileUnk]); + if (stage > 2) { + shade = stage; + } + } else if ((logic & L_TREE_VARIATION) != 0) { + shade = 5; + } + + /* first ray: along the light's diagonal, shading hardest close to the tileUnk */ + int rayTile = tileUnk; + int rayY = y; + uint step = 6; + do { + rayTile = rayTile + this->directionTranslationMatrix[rayY][diagonal]; + rayY = rayY + DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[diagonal].int_.yOffset; + if ((this->LogicLayer[rayTile] & (L_BORDER | L_BORDER_EDGE)) != 0) { + break; + } + if ((this->LogicLayer[rayTile] & (L_BUILDING | L_KEEP_NON_MANOR_HOUSE)) == 0) { + high = this->HeightLayer[rayTile]; + } else if (MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::getBuildingFlag3, DAT_BuildingsState::ptr)( + this->BuildingLayer[rayTile]) + == 0) { + if ((int)MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::getBuildingHeightForBuildingID, DAT_BuildingsState::ptr)( + this->BuildingLayer[rayTile]) + < 0x10) { + high = this->HeightLayer[rayTile] + 0x10; + } else { + high = (uint)this->HeightLayer[rayTile] + + MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::getBuildingHeightForBuildingID, DAT_BuildingsState::ptr)( + this->BuildingLayer[rayTile]); + } + } + if ((this->LogicLayer[rayTile] & L_TREE) != 0) { + high = high + + MACRO_CALL_MEMBER(OpenSHC::Map::LandscapeState_Func::getTreeGrowthTargetStage, DAT_LandscapeState::ptr)( + this->OrganismLayer[rayTile]) + * 7; + } else if ((this->LogicLayer[rayTile] & L_TREE_VARIATION) != 0) { + high = high + 0x28; + } + int rise = high - ownHeight; + uint lit; + if (rise <= 0) { + lit = 2; + } else if (rise > 0x12) { + lit = step + 1; + } else if (rise > 0xe) { + lit = step; + } else if (rise > 0xa) { + lit = step + -1; + } else if (rise > 6) { + lit = step + -2; + } else if (rise > 2) { + lit = step + -3; + } else { + lit = 0; + } + if (shade < (int)lit) { + shade = lit; + } + step = step - 1; + } while ((int)step > 1); + + /* second ray: one cardinal step off the diagonal */ + rayTile = this->directionTranslationMatrix[y][along] + tileUnk; + rayY = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[along].int_.yOffset + y; + along = 4; + uint sampled = high; + do { + if ((this->LogicLayer[rayTile] & (L_BORDER | L_BORDER_EDGE)) != 0) { + break; + } + if ((this->LogicLayer[rayTile] & (L_BUILDING | L_KEEP_NON_MANOR_HOUSE)) == 0) { + sampled = this->HeightLayer[rayTile]; + } else if (MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::getBuildingFlag3, + DAT_BuildingsState::ptr)(this->BuildingLayer[rayTile]) + == 0) { + if ((int)MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::getBuildingHeightForBuildingID, DAT_BuildingsState::ptr)( + this->BuildingLayer[rayTile]) + < 0x10) { + sampled = this->HeightLayer[rayTile] + 0x10; + } else { + sampled = (uint)this->HeightLayer[rayTile] + + MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::getBuildingHeightForBuildingID, + DAT_BuildingsState::ptr)(this->BuildingLayer[rayTile]); + } + } + if ((this->LogicLayer[rayTile] & L_TREE) != 0) { + sampled = sampled + + MACRO_CALL_MEMBER(OpenSHC::Map::LandscapeState_Func::getTreeGrowthTargetStage, + DAT_LandscapeState::ptr)(this->OrganismLayer[rayTile]) + * 7; + } else if ((this->LogicLayer[rayTile] & L_TREE_VARIATION) != 0) { + sampled = sampled + 0x28; + } + int rise = sampled - ownHeight; + if (rise <= 0) { + high = 2; + } else if (rise > 0x12) { + high = along + 1; + } else if (rise > 0xc) { + high = along; + } else if (rise > 6) { + high = along - 1; + } else { + high = 0; + } + if (alongShade < (int)high) { + alongShade = high; + } + rayTile = rayTile + this->directionTranslationMatrix[rayY][diagonal]; + along = along - 1; + rayY = rayY + DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[diagonal].int_.yOffset; + } while (along > -1); + + /* third ray: the same, one cardinal step the other way */ + rayTile = this->directionTranslationMatrix[y][across] + tileUnk; + rayY = DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[across].int_.yOffset + y; + across = 4; + do { + if ((this->LogicLayer[rayTile] & (L_BORDER | L_BORDER_EDGE)) != 0) { + break; + } + if ((this->LogicLayer[rayTile] & (L_BUILDING | L_KEEP_NON_MANOR_HOUSE)) == 0) { + sampled = this->HeightLayer[rayTile]; + } else if (MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::getBuildingFlag3, + DAT_BuildingsState::ptr)(this->BuildingLayer[rayTile]) + == 0) { + if ((int)MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::getBuildingHeightForBuildingID, DAT_BuildingsState::ptr)( + this->BuildingLayer[rayTile]) + < 0x10) { + sampled = this->HeightLayer[rayTile] + 0x10; + } else { + sampled = (uint)this->HeightLayer[rayTile] + + MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::getBuildingHeightForBuildingID, + DAT_BuildingsState::ptr)(this->BuildingLayer[rayTile]); + } + } + if ((this->LogicLayer[rayTile] & L_TREE) != 0) { + sampled = sampled + + MACRO_CALL_MEMBER(OpenSHC::Map::LandscapeState_Func::getTreeGrowthTargetStage, + DAT_LandscapeState::ptr)(this->OrganismLayer[rayTile]) + * 7; + } else if ((this->LogicLayer[rayTile] & L_TREE_VARIATION) != 0) { + sampled = sampled + 0x28; + } + int rise = sampled - ownHeight; + if (rise <= 0) { + high = 2; + } else if (rise > 0x12) { + high = across + 1; + } else if (rise > 0xc) { + high = across; + } else if (rise > 6) { + high = across - 1; + } else { + high = 0; + } + if (acrossShade < (int)high) { + acrossShade = high; + } + rayTile = rayTile + this->directionTranslationMatrix[rayY][diagonal]; + across = across - 1; + rayY = rayY + DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[diagonal].int_.yOffset; + } while (across > -1); + + if (shade + -2 < (int)((acrossShade - 4) + alongShade)) { + shade = (acrossShade - 2) + alongShade; + if (shade > 6) { + shade = 7; + } + } else if (shade == 2) { + /* nothing casts onto the tileUnk, so shade it by the slope it sits on */ + int diagonalTile = this->directionTranslationMatrix[y][diagonal] + tileUnk; + uint lightSide = ownHeight; + if ((this->LogicLayer[diagonalTile] & (L_BORDER | L_BORDER_EDGE)) == 0) { + if ((this->LogicLayer[diagonalTile] & (L_BUILDING | L_KEEP_NON_MANOR_HOUSE)) == 0) { + lightSide = this->HeightLayer[diagonalTile]; + } else { + lightSide = sampled; + if (MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::getBuildingFlag3, + DAT_BuildingsState::ptr)(this->BuildingLayer[diagonalTile]) + == 0) { + if ((int)MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::getBuildingHeightForBuildingID, DAT_BuildingsState::ptr)( + this->BuildingLayer[diagonalTile]) + < 0x10) { + lightSide = this->HeightLayer[diagonalTile] + 0x10; + } else { + lightSide = (uint)this->HeightLayer[diagonalTile] + + MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::getBuildingHeightForBuildingID, + DAT_BuildingsState::ptr)(this->BuildingLayer[diagonalTile]); + } + } + } + } + int oppositeTile = this->directionTranslationMatrix[y][opposite] + tileUnk; + uint darkSide = ownHeight; + if ((this->LogicLayer[oppositeTile] & (L_BORDER | L_BORDER_EDGE)) == 0) { + darkSide = this->HeightLayer[oppositeTile]; + } + if ((int)lightSide < (int)(ownHeight - 4)) { + slope = 1; + } + if (ownHeight + 4 < darkSide) { + slope = slope + 1; + } + if ((this->LogicLayer[tileUnk] & L_MOAT) == 0) { + if (slope == 1) { + shade = 1; + } else if (slope == 2) { + shade = 0; + } + } + } + this->LuminesenceLayer[tileUnk] = (uchar)shade; + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/computeWallCornerRenderRotation.cpp b/src/OpenSHC/Map/TileMapState/computeWallCornerRenderRotation.cpp new file mode 100644 index 0000000000..da3d233508 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/computeWallCornerRenderRotation.cpp @@ -0,0 +1,84 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x004FC650 + int TileMapState::computeWallCornerRenderRotation(uint x) + { + int tileUnk = this->DAT_SomeTile; + int y = this->DAT_SomeY; + int result = 0; + if (MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::isWallConnectionHeightValid, this)(tileUnk, y, 2) + != FALSE) { + if (this->mapOrientation == 0) { + if ((x & 0xf) == 0xf) { + result = 2; + } else { + result = 0x11 - (x & 0xf); + } + } else if (this->mapOrientation == 4) { + if ((x & 0xf) == 0) { + result = 2; + } else { + result = (x & 0xf) + 2; + } + } else if (this->mapOrientation == 2) { + if ((x & 0xf) == 0) { + result = 1; + } else { + result = (x & 0xf) + 0x11; + } + } else if (this->mapOrientation == 6) { + if ((x & 0xf) == 0xf) { + result = 1; + } else { + result = 0x20 - (x & 0xf); + } + } + } else if (MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::isWallConnectionHeightValid, this)(tileUnk, y, 0) + != FALSE) { + if (this->mapOrientation == 0) { + if ((y & 0xf) == 0xf) { + result = 1; + } else { + result = 0x20 - (y & 0xf); + } + } else if (this->mapOrientation == 4) { + if ((y & 0xf) == 0) { + result = 1; + } else { + result = (y & 0xf) + 0x11; + } + } else if (this->mapOrientation == 6) { + if ((y & 0xf) == 0) { + result = 2; + } else { + result = (y & 0xf) + 2; + } + } else if (this->mapOrientation == 2) { + if ((y & 0xf) == 0xf) { + result = 2; + } else { + result = 0x11 - (y & 0xf); + } + } + } else if (MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getWallFlagForOrientedDirection, this)(tileUnk, y, 2) + != 0) { + result = 48; + } else { + /* 0x3f when the other direction carries a wall too, 0x21 when it does not */ + result = (-(uint)(MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getWallFlagForOrientedDirection, this)( + tileUnk, y, 4) + != 0) + & 0x1e) + + 0x21; + } + return result; + } +} +} diff --git a/src/OpenSHC/Map/TileMapState/countLogicPropertyInSurroundingTiles.cpp b/src/OpenSHC/Map/TileMapState/countLogicPropertyInSurroundingTiles.cpp new file mode 100644 index 0000000000..95f8d15a0f --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/countLogicPropertyInSurroundingTiles.cpp @@ -0,0 +1,25 @@ +#include "../TileMapState.func.hpp" + +namespace OpenSHC { +namespace Map { + + // FUNCTION: STRONGHOLDCRUSADER 0x004F8530 + void TileMapState::countLogicPropertyInSurroundingTiles(int tile, int y, uint logic1) + { + this->DAT_CardinalTilesAroundTile = 0; + if ((this->LogicLayer[this->directionTranslationMatrix[y][0] + tile] & logic1) != 0) { + this->DAT_CardinalTilesAroundTile++; + } + if ((this->LogicLayer[this->directionTranslationMatrix[y][2] + tile] & logic1) != 0) { + this->DAT_CardinalTilesAroundTile++; + } + if ((this->LogicLayer[this->directionTranslationMatrix[y][4] + tile] & logic1) != 0) { + this->DAT_CardinalTilesAroundTile++; + } + if ((this->LogicLayer[this->directionTranslationMatrix[y][6] + tile] & logic1) != 0) { + this->DAT_CardinalTilesAroundTile++; + } + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/countMoatsOwnedByEachPlayer.cpp b/src/OpenSHC/Map/TileMapState/countMoatsOwnedByEachPlayer.cpp new file mode 100644 index 0000000000..2e3c9d6d91 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/countMoatsOwnedByEachPlayer.cpp @@ -0,0 +1,29 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Globals/DAT_GameState.hpp" + +namespace OpenSHC { +namespace Map { + + // FUNCTION: STRONGHOLDCRUSADER 0x005000E0 + void TileMapState::countMoatsOwnedByEachPlayer() + { + DAT_GameState::instance.playerDataArray[1].moatsOwned = 0; + DAT_GameState::instance.playerDataArray[2].moatsOwned = 0; + DAT_GameState::instance.playerDataArray[3].moatsOwned = 0; + DAT_GameState::instance.playerDataArray[4].moatsOwned = 0; + DAT_GameState::instance.playerDataArray[5].moatsOwned = 0; + DAT_GameState::instance.playerDataArray[6].moatsOwned = 0; + DAT_GameState::instance.playerDataArray[7].moatsOwned = 0; + DAT_GameState::instance.playerDataArray[8].moatsOwned = 0; + for (int moatID = 1; moatID < 16000; moatID++) { + char owner = this->moats[moatID].owner; + if (owner != 0) { + DAT_GameState::instance.playerDataArray[owner].moatsOwned + = DAT_GameState::instance.playerDataArray[owner].moatsOwned + 1; + } + } + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/countUnfinishedMoatTilesForPlayer.cpp b/src/OpenSHC/Map/TileMapState/countUnfinishedMoatTilesForPlayer.cpp new file mode 100644 index 0000000000..94d1f7836b --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/countUnfinishedMoatTilesForPlayer.cpp @@ -0,0 +1,22 @@ +#include "../TileMapState.func.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_MOAT; + + // FUNCTION: STRONGHOLDCRUSADER 0x00500180 + int TileMapState::countUnfinishedMoatTilesForPlayer(int playerID) + { + int unfinishedMoatTiles = 0; + for (int moatID = 1; moatID < 16000; moatID++) { + if (this->moats[moatID].owner != 0 && this->moats[moatID].owner == playerID + && (this->LogicLayer[this->moats[moatID].tile] & L_MOAT) == 0) { + unfinishedMoatTiles++; + } + } + return unfinishedMoatTiles; + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/countUnownedPitchDitches.cpp b/src/OpenSHC/Map/TileMapState/countUnownedPitchDitches.cpp new file mode 100644 index 0000000000..018ebbd565 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/countUnownedPitchDitches.cpp @@ -0,0 +1,19 @@ +#include "../TileMapState.func.hpp" + +namespace OpenSHC { +namespace Map { + + // FUNCTION: STRONGHOLDCRUSADER 0x00500800 + int TileMapState::countUnownedPitchDitches() + { + int unownedPitchDitches = 0; + for (int pitchDitchID = 0; pitchDitchID < 4000; pitchDitchID++) { + if (this->pitchDitches[pitchDitchID].owner == 0) { + unownedPitchDitches++; + } + } + return unownedPitchDitches; + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/createMoatData.cpp b/src/OpenSHC/Map/TileMapState/createMoatData.cpp new file mode 100644 index 0000000000..de3dc23589 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/createMoatData.cpp @@ -0,0 +1,65 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Map/Buildings/BuildingsState.func.hpp" +#include "OpenSHC/Game/GameMode2.hpp" + +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_GameCore.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Game::GameMode2; + + // FUNCTION: STRONGHOLDCRUSADER 0x005110B0 + int TileMapState::createMoatData(undefined4 playerID, uint x, uint y, int filled) + { + if (x > 399 || y > 399) { + return 0; + } + if (DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[y * 400 + x] == 0) { + return 0; + } + + int existingMoatID = MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::returnOwnedMoatAtTile, this)( + DAT_ViewportRenderState::instance.translationMatrix[y].addXgetTile + x); + if (existingMoatID != 0) { + return existingMoatID; + } + if (DAT_GameCore::instance.gameMode_2 == OpenSHC::Game::GM_SIEGE_THAT + && MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::hasEnoughGoldForMoat, DAT_BuildingsState::ptr)() + == 0) { + return 0; + } + + for (int moatID = 1; moatID < 16000; moatID++) { + if (this->moats[moatID].owner != 0) { + continue; + } + + if (this->currentMoatCount <= moatID) { + this->currentMoatCount = moatID + 1; + } + this->moats[moatID].owner = (char)playerID; + this->moats[moatID].x = (short)x; + this->moats[moatID].y = (short)y; + this->moats[moatID].tile = DAT_ViewportRenderState::instance.translationMatrix[y].addXgetTile + x; + this->moats[moatID].zeroOrTwo = 2; + if (filled == 0) { + this->moats[moatID].stage = 1; + this->moats[moatID].fillProgress = 0; + this->moatTileCount = this->moatTileCount + 1; + return moatID; + } + this->moats[moatID].stage = 2; + this->moats[moatID].fillProgress = 4; + this->moatTileCount = this->moatTileCount + 1; + return moatID; + } + return 0; + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/createPlateau.cpp b/src/OpenSHC/Map/TileMapState/createPlateau.cpp new file mode 100644 index 0000000000..bf4cabf625 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/createPlateau.cpp @@ -0,0 +1,80 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" +#include "OpenSHC/Map/TileMapState/NeighbourFlagsAsm.hpp" + +#include "OpenSHC/Globals/DAT_PathFindingState.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_BORDER; + using OpenSHC::Map::LogicHelpers::L_BORDER_EDGE; + using OpenSHC::Map::LogicHelpers::L_BUILDING; + using OpenSHC::Map::LogicHelpers::L_KEEP_NON_MANOR_HOUSE; + using OpenSHC::Map::LogicHelpers::L_MARSH; + using OpenSHC::Map::LogicHelpers::L_MOAT; + using OpenSHC::Map::LogicHelpers::L_MOAT_DUG_OR_PLANNED; + using OpenSHC::Map::LogicHelpers::L_RIVER; + using OpenSHC::Map::LogicHelpers::L_ROCKY; + using OpenSHC::Map::LogicHelpers::L_SEA; + using OpenSHC::Map::LogicHelpers::L_WALL_OR_GATEHOUSE; + + // FUNCTION: STRONGHOLDCRUSADER 0x00501F50 + void TileMapState::createPlateau(int tile, uint the_y, int brush, int plateauHeightSetting) + { + int baseTile = tile; + uint baseY = the_y; + /* the original reuses the brush parameter to hold the size */ + brush = DAT_TerrainDefinedData::instance.BrushSizeArray[brush]; + + int maxHeightInBrush = 0; + for (int index = 0; index < brush; index++) { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getTileForBrush, this)( + 1, index, &tile, (int*)&the_y, baseTile, baseY); + if ((this->LogicLayer[tile] & (L_BORDER | L_BORDER_EDGE)) == 0 + && this->HeightLayer[tile] > maxHeightInBrush) { + maxHeightInBrush = this->HeightLayer[tile]; + } + } + + tile = baseTile; + the_y = baseY; + for (int index = 0; index < brush; index++) { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getTileForBrush, this)( + 1, index, &tile, (int*)&the_y, baseTile, baseY); + int brushTile = tile; + uint logic = this->LogicLayer[brushTile]; + if ((logic & (L_BORDER | L_BORDER_EDGE)) == 0 + && (logic & (L_SEA | L_BUILDING | L_KEEP_NON_MANOR_HOUSE | L_MARSH | L_MOAT)) == 0 + && this->BuildingLayer[brushTile] == 0 + && (logic + & (L_WALL_OR_GATEHOUSE | L_BUILDING | L_MOAT_DUG_OR_PLANNED | L_KEEP_NON_MANOR_HOUSE | L_MOAT)) + == 0) { + this->LogicLayer[brushTile] = this->LogicLayer[brushTile] & ~L_ROCKY; + if (plateauHeightSetting == 4) { + this->HeightLayer[brushTile] = 80; + } else if (plateauHeightSetting == 8) { + this->HeightLayer[brushTile] = 130; + } + this->DefaultHeightLayer[brushTile] = this->HeightLayer[brushTile]; + if ((this->LogicLayer[brushTile] & L_RIVER) != 0) { + this->HeightLayer[brushTile] = this->HeightLayer[brushTile] - 8; + } + uint brushY = the_y; + this->Logic2Layer[brushTile] = (byte)plateauHeightSetting; + this->DAT_SomeTile = brushTile; + this->DAT_SomeY = brushY; + + /* handwritten assembly in the original: mark this tile and its eight neighbours changed */ + MACRO_MARK_CHANGED_NEIGHBOURS() + MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::PathFindingState_Func::updatePathLinkagesInAllEightDirections, + DAT_PathFindingState::ptr)(brushY, brushTile); + } + } + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/createWaterForDrawBridge.cpp b/src/OpenSHC/Map/TileMapState/createWaterForDrawBridge.cpp new file mode 100644 index 0000000000..30d3140bfd --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/createWaterForDrawBridge.cpp @@ -0,0 +1,47 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" + +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_PathFindingState.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_MOAT; + + // FUNCTION: STRONGHOLDCRUSADER 0x00515C80 + void TileMapState::createWaterForDrawBridge(int buildingID) + { + uint xPosition = DAT_BuildingsState::instance.buildings[buildingID].x; + uint widthOrHeight = DAT_BuildingsState::instance.buildings[buildingID].widthOrHeight; + uint yPosition = DAT_BuildingsState::instance.buildings[buildingID].y; + int variation = DAT_BuildingsState::instance.buildings[buildingID].buildingVariation / 2; + int buildingSizeTileIndex = 0; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)( + buildingSizeTileIndex, 5); + uint footprintY = yPosition + this->buildingY; + int tile = DAT_ViewportRenderState::instance.translationMatrix[footprintY].addXgetTile + this->buildingX + + xPosition; + if (DAT_TerrainDefinedData::instance.DrawbridgeOrientationMapping[variation][buildingSizeTileIndex] != 0) { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::createMoatData, this)( + DAT_BuildingsState::instance.buildings[buildingID].owner, this->buildingX + xPosition, footprintY, + 1); + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_MOAT; + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::setMoatVisualStateAtTile, this)(tile, 0); + this->HeightLayer[tile] = 0; + } + buildingSizeTileIndex++; + } while (buildingSizeTileIndex < this->constructionTileCount); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::updateBuildingGraphicsLayer, this)(buildingID); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::updatePathLinkagesForBuilding, this)(buildingID); + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::updateWalkAndPathLayer, + DAT_PathFindingState::ptr)(widthOrHeight + 6, xPosition, yPosition); + DAT_PathFindingState::instance.toggleUpdateSeparateAreaTileMap = 1; + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/demolishBuildingsInKeepsConstructionFootprint.cpp b/src/OpenSHC/Map/TileMapState/demolishBuildingsInKeepsConstructionFootprint.cpp new file mode 100644 index 0000000000..3c0b3ceeb6 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/demolishBuildingsInKeepsConstructionFootprint.cpp @@ -0,0 +1,97 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Map/Buildings/BuildingsState.func.hpp" +#include "OpenSHC/Map/Buildings/BuildingLogicalState.hpp" + +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::Buildings::BuildingLogicalState; + + // FUNCTION: STRONGHOLDCRUSADER 0x004FA760 + void TileMapState::demolishBuildingsInKeepsConstructionFootprint( + undefined4 param_1, int x, int y, undefined4 buildingType, int sizeIndex, int param_6, int param_7) + { + int keepX = x; + int keepY = y; + int index = 0; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)(index, sizeIndex); + int tileUnk = DAT_ViewportRenderState::instance.translationMatrix[this->buildingY + y].addXgetTile + this->buildingX + x; + if (this->BuildingLayer[tileUnk] != 0) { + this->showNoRubbleWhenDestroyingBuilding = 1; + MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::destroyBuilding, DAT_BuildingsState::ptr)(this->BuildingLayer[tileUnk]); + } + index++; + } while (index < this->constructionTileCount); + + /* the keep drags three towers and two outbuildings with it, laid out per keep variant */ + int variant = (short)buildingType - 0x28; + { + int tileUnk = DAT_ViewportRenderState::instance.translationMatrix[DAT_TerrainDefinedData::instance.field130_0x264[variant][0].y + y].addXgetTile + + DAT_TerrainDefinedData::instance.field130_0x264[variant][0].x + x; + if (this->BuildingLayer[tileUnk] != 0) { + this->showNoRubbleWhenDestroyingBuilding = 1; + MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::destroyBuilding, DAT_BuildingsState::ptr)(this->BuildingLayer[tileUnk]); + } + } + + { + int tileUnk = DAT_ViewportRenderState::instance.translationMatrix[DAT_TerrainDefinedData::instance.field130_0x264[variant][1].y + y].addXgetTile + + DAT_TerrainDefinedData::instance.field130_0x264[variant][1].x + x; + if (this->BuildingLayer[tileUnk] != 0) { + this->showNoRubbleWhenDestroyingBuilding = 1; + MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::destroyBuilding, DAT_BuildingsState::ptr)(this->BuildingLayer[tileUnk]); + } + } + + { + int tileUnk = DAT_ViewportRenderState::instance.translationMatrix[DAT_TerrainDefinedData::instance.field130_0x264[variant][2].y + y].addXgetTile + + DAT_TerrainDefinedData::instance.field130_0x264[variant][2].x + x; + if (this->BuildingLayer[tileUnk] != 0) { + this->showNoRubbleWhenDestroyingBuilding = 1; + MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::destroyBuilding, DAT_BuildingsState::ptr)(this->BuildingLayer[tileUnk]); + } + } + + x = x + DAT_TerrainDefinedData::instance.keepOutbuildingOffsets_0x384[variant][0].xOffset; + y = y + DAT_TerrainDefinedData::instance.keepOutbuildingOffsets_0x384[variant][0].yOffset; + index = 0; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)(index, 7); + int tileUnk = DAT_ViewportRenderState::instance.translationMatrix[this->buildingY + y].addXgetTile + this->buildingX + x; + if (this->BuildingLayer[tileUnk] != 0) { + this->showNoRubbleWhenDestroyingBuilding = 1; + MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::destroyBuilding, DAT_BuildingsState::ptr)(this->BuildingLayer[tileUnk]); + } + index++; + } while (index < this->constructionTileCount); + + x = keepX + DAT_TerrainDefinedData::instance.keepOutbuildingOffsets_0x3e4[variant][0].xOffset; + y = keepY + DAT_TerrainDefinedData::instance.keepOutbuildingOffsets_0x3e4[variant][0].yOffset; + index = 0; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)(index, 5); + int tileUnk = DAT_ViewportRenderState::instance.translationMatrix[this->buildingY + y].addXgetTile + this->buildingX + x; + if (this->BuildingLayer[tileUnk] != 0) { + this->showNoRubbleWhenDestroyingBuilding = 1; + MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::destroyBuilding, DAT_BuildingsState::ptr)(this->BuildingLayer[tileUnk]); + } + index++; + } while (index < this->constructionTileCount); + + for (int buildingID = 1; buildingID < 2000; buildingID++) { + if (DAT_BuildingsState::instance.buildings[buildingID].logicalState + == OpenSHC::Map::Buildings::BLS_REMOVE) { + MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::deleteBuilding, DAT_BuildingsState::ptr)(buildingID); + } + } + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/destroyPitchDitch.cpp b/src/OpenSHC/Map/TileMapState/destroyPitchDitch.cpp new file mode 100644 index 0000000000..d046dd4219 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/destroyPitchDitch.cpp @@ -0,0 +1,36 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/IO/LowLevelMemory.func.hpp" +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" + +#include "OpenSHC/Globals/DAT_LowLevelMemory.hpp" +#include "OpenSHC/Globals/DAT_PathFindingState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_PLAIN2_AND_PITCH; + using OpenSHC::Map::LogicHelpers::L_WALL_OR_GATEHOUSE; + + // FUNCTION: STRONGHOLDCRUSADER 0x00500890 + void TileMapState::destroyPitchDitch(int pitchDitchID) + { + this->LogicLayer[this->pitchDitches[pitchDitchID].tile] + = this->LogicLayer[this->pitchDitches[pitchDitchID].tile] & ~L_PLAIN2_AND_PITCH; + this->MiscDisplayLayer[this->pitchDitches[pitchDitchID].tile] + = this->MiscDisplayLayer[this->pitchDitches[pitchDitchID].tile] & ~0x2000; + this->MiscDisplayLayer[this->pitchDitches[pitchDitchID].tile] + = this->MiscDisplayLayer[this->pitchDitches[pitchDitchID].tile] & ~0x4000; + if ((this->LogicLayer[this->pitchDitches[pitchDitchID].tile] & L_WALL_OR_GATEHOUSE) == 0 + && this->BuildingLayer[this->pitchDitches[pitchDitchID].tile] == 0) { + this->HeightLayer[this->pitchDitches[pitchDitchID].tile] + = this->DefaultHeightLayer[this->pitchDitches[pitchDitchID].tile]; + } + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::updateWalkAndPathLayer, + DAT_PathFindingState::ptr)(4, this->pitchDitches[pitchDitchID].x, this->pitchDitches[pitchDitchID].y); + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + sizeof(PitchDitch), 0, &this->pitchDitches[pitchDitchID]); + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/destroyWallsOfPlayer.cpp b/src/OpenSHC/Map/TileMapState/destroyWallsOfPlayer.cpp new file mode 100644 index 0000000000..1a39c7b97a --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/destroyWallsOfPlayer.cpp @@ -0,0 +1,56 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Map/Entities/EntityState.func.hpp" +#include "OpenSHC/Map/MapConstants.hpp" +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" + +#include "OpenSHC/Globals/DAT_EntityState.hpp" +#include "OpenSHC/Globals/DAT_PathFindingState.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_CRENEL; + using OpenSHC::Map::LogicHelpers::L_CRENEL_VARIATIONUnk; + using OpenSHC::Map::LogicHelpers::L_STAIRS; + using OpenSHC::Map::LogicHelpers::L_UNKNOWN_WALL_RELATED; + using OpenSHC::Map::LogicHelpers::L_WALL_OR_GATEHOUSE; + + using OpenSHC::Map::LogicHelpers::L_CRENEL; + using OpenSHC::Map::LogicHelpers::L_CRENEL_VARIATIONUnk; + using OpenSHC::Map::LogicHelpers::L_STAIRS; + using OpenSHC::Map::LogicHelpers::L_UNKNOWN_WALL_RELATED; + using OpenSHC::Map::LogicHelpers::L_WALL_OR_GATEHOUSE; + + // FUNCTION: STRONGHOLDCRUSADER 0x004F93E0 + void TileMapState::destroyWallsOfPlayer(int playerID) + { + for (int tile = 0; tile < MC_MAP_TILES_COUNT; tile++) { + if ((this->LogicLayer[tile] & L_WALL_OR_GATEHOUSE) == 0) { + continue; + } + if ((this->WallOwnerLayer[tile] & 7) + 1 != playerID) { + continue; + } + + MACRO_CALL_MEMBER(OpenSHC::Map::Entities::EntityState_Func::destroyEntitiesOnTile, DAT_EntityState::ptr)( + tile); + this->LogicLayer[tile] = this->LogicLayer[tile] + & ~(L_WALL_OR_GATEHOUSE | L_CRENEL | L_STAIRS | L_UNKNOWN_WALL_RELATED | L_CRENEL_VARIATIONUnk); + this->HeightLayer[tile] = this->DefaultHeightLayer[tile]; + this->DamageLayer[tile] = 0; + uint y = DAT_ViewportRenderState::instance.tileTranslationMatrix_YComponent[tile]; + DAT_PathFindingState::instance.toggleUpdateSeparateAreaTileMap = 1; + DAT_TileMapState::instance.field204_0x554a30 = 1; + int x = tile - DAT_ViewportRenderState::instance.translationMatrix[y].addXgetTile; + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::updatePathLinkagesInAllEightDirections, + DAT_PathFindingState::ptr)(y, tile); + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::updateWalkAndPathLayer, + DAT_PathFindingState::ptr)(7, x, y); + } + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/determineBuildingPlacementRotation.cpp b/src/OpenSHC/Map/TileMapState/determineBuildingPlacementRotation.cpp new file mode 100644 index 0000000000..672c7a8c4f --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/determineBuildingPlacementRotation.cpp @@ -0,0 +1,167 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_STAIRS; + using OpenSHC::Map::LogicHelpers::L_STOCKPILEUnk; + using OpenSHC::Map::LogicHelpers::L_WALL_OR_GATEHOUSE; + + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x004FA000 + void TileMapState::determineBuildingPlacementRotation(int x, int y) + { + if (this->buildingPlacementFail != FALSE) { + this->uiBuildingRotation = 8; + this->field127_0x554944 = 0x80; + return; + } + + /* count, per rotation, how many of its four anchor tiles carry usable wall */ + int walls[4]; + for (int rotation = 0; rotation < 4; rotation++) { + walls[rotation] = 0; + if ((uint)(DAT_TerrainDefinedData::instance.field2334_0x1e4c[rotation * 8 + 0] + x) <= 399 + && (uint)(DAT_TerrainDefinedData::instance.field2334_0x1e4c[rotation * 8 + 1] + y) <= 399 + && DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400 + [(DAT_TerrainDefinedData::instance.field2334_0x1e4c[rotation * 8 + 1] + y) * 400 + + DAT_TerrainDefinedData::instance.field2334_0x1e4c[rotation * 8 + 0] + x] + != 0 + && (this->LogicLayer[DAT_ViewportRenderState::instance + .translationMatrix + [DAT_TerrainDefinedData::instance.field2334_0x1e4c[rotation * 8 + 1] + y] + .addXgetTile + + DAT_TerrainDefinedData::instance.field2334_0x1e4c[rotation * 8 + 0] + x] + & L_WALL_OR_GATEHOUSE) + != 0 + && (this->LogicLayer[DAT_ViewportRenderState::instance + .translationMatrix + [DAT_TerrainDefinedData::instance.field2334_0x1e4c[rotation * 8 + 1] + y] + .addXgetTile + + DAT_TerrainDefinedData::instance.field2334_0x1e4c[rotation * 8 + 0] + x] + & (L_STOCKPILEUnk | L_STAIRS)) + == 0) { + walls[rotation] = 1; + } + if ((uint)(DAT_TerrainDefinedData::instance.field2334_0x1e4c[rotation * 8 + 2] + x) <= 399 + && (uint)(DAT_TerrainDefinedData::instance.field2334_0x1e4c[rotation * 8 + 3] + y) <= 399 + && DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400 + [(DAT_TerrainDefinedData::instance.field2334_0x1e4c[rotation * 8 + 3] + y) * 400 + + DAT_TerrainDefinedData::instance.field2334_0x1e4c[rotation * 8 + 2] + x] + != 0 + && (this->LogicLayer[DAT_ViewportRenderState::instance + .translationMatrix + [DAT_TerrainDefinedData::instance.field2334_0x1e4c[rotation * 8 + 3] + y] + .addXgetTile + + DAT_TerrainDefinedData::instance.field2334_0x1e4c[rotation * 8 + 2] + x] + & L_WALL_OR_GATEHOUSE) + != 0 + && (this->LogicLayer[DAT_ViewportRenderState::instance + .translationMatrix + [DAT_TerrainDefinedData::instance.field2334_0x1e4c[rotation * 8 + 3] + y] + .addXgetTile + + DAT_TerrainDefinedData::instance.field2334_0x1e4c[rotation * 8 + 2] + x] + & (L_STOCKPILEUnk | L_STAIRS)) + == 0) { + walls[rotation] = walls[rotation] + 1; + } + if ((uint)(DAT_TerrainDefinedData::instance.field2334_0x1e4c[rotation * 8 + 4] + x) <= 399 + && (uint)(DAT_TerrainDefinedData::instance.field2334_0x1e4c[rotation * 8 + 5] + y) <= 399 + && DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400 + [(DAT_TerrainDefinedData::instance.field2334_0x1e4c[rotation * 8 + 5] + y) * 400 + + DAT_TerrainDefinedData::instance.field2334_0x1e4c[rotation * 8 + 4] + x] + != 0 + && (this->LogicLayer[DAT_ViewportRenderState::instance + .translationMatrix + [DAT_TerrainDefinedData::instance.field2334_0x1e4c[rotation * 8 + 5] + y] + .addXgetTile + + DAT_TerrainDefinedData::instance.field2334_0x1e4c[rotation * 8 + 4] + x] + & L_WALL_OR_GATEHOUSE) + != 0 + && (this->LogicLayer[DAT_ViewportRenderState::instance + .translationMatrix + [DAT_TerrainDefinedData::instance.field2334_0x1e4c[rotation * 8 + 5] + y] + .addXgetTile + + DAT_TerrainDefinedData::instance.field2334_0x1e4c[rotation * 8 + 4] + x] + & (L_STOCKPILEUnk | L_STAIRS)) + == 0) { + walls[rotation] = walls[rotation] + 1; + } + if ((uint)(DAT_TerrainDefinedData::instance.field2334_0x1e4c[rotation * 8 + 6] + x) <= 399 + && (uint)(DAT_TerrainDefinedData::instance.field2334_0x1e4c[rotation * 8 + 7] + y) <= 399 + && DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400 + [(DAT_TerrainDefinedData::instance.field2334_0x1e4c[rotation * 8 + 7] + y) * 400 + + DAT_TerrainDefinedData::instance.field2334_0x1e4c[rotation * 8 + 6] + x] + != 0 + && (this->LogicLayer[DAT_ViewportRenderState::instance + .translationMatrix + [DAT_TerrainDefinedData::instance.field2334_0x1e4c[rotation * 8 + 7] + y] + .addXgetTile + + DAT_TerrainDefinedData::instance.field2334_0x1e4c[rotation * 8 + 6] + x] + & L_WALL_OR_GATEHOUSE) + != 0 + && (this->LogicLayer[DAT_ViewportRenderState::instance + .translationMatrix + [DAT_TerrainDefinedData::instance.field2334_0x1e4c[rotation * 8 + 7] + y] + .addXgetTile + + DAT_TerrainDefinedData::instance.field2334_0x1e4c[rotation * 8 + 6] + x] + & (L_STOCKPILEUnk | L_STAIRS)) + == 0) { + walls[rotation] = walls[rotation] + 1; + } + } + + bool decided = false; + if (walls[0] == 4) { + if (walls[3] == 4) { + this->uiBuildingRotation = 7; + decided = true; + } else if (walls[1] == 4) { + this->uiBuildingRotation = 1; + decided = true; + } + } + if (!decided && walls[2] == 4) { + if (walls[3] == 4) { + this->uiBuildingRotation = 5; + decided = true; + } else if (walls[1] == 4) { + this->uiBuildingRotation = 3; + decided = true; + } + } + if (!decided) { + if (walls[0] == 4) { + this->uiBuildingRotation = 0; + } else if (walls[1] == 4) { + this->uiBuildingRotation = 2; + } else if (walls[2] == 4) { + this->uiBuildingRotation = 4; + } else if (walls[3] == 4) { + this->uiBuildingRotation = 6; + } else { + this->uiBuildingRotation = 8; + } + } + + int relative; + if (this->uiBuildingRotation == 8) { + relative = 8; + } else { + relative = this->uiBuildingRotation - this->mapOrientation; + if (relative < 0) { + this->field127_0x554944 = (relative + 8) * 0x10; + return; + } + } + this->field127_0x554944 = relative << 4; + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/eraseAreaWithBrush.cpp b/src/OpenSHC/Map/TileMapState/eraseAreaWithBrush.cpp new file mode 100644 index 0000000000..c4b0fb4ddb --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/eraseAreaWithBrush.cpp @@ -0,0 +1,140 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Map/Buildings/BuildingsState.func.hpp" +#include "OpenSHC/Map/LandscapeState.func.hpp" +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" +#include "OpenSHC/Map/Buildings/BuildingType.hpp" +#include "OpenSHC/Map/Units/UnitLogicState.hpp" +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_GameState.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_UnitsState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_BORDER; + using OpenSHC::Map::LogicHelpers::L_BORDER_EDGE; + + using OpenSHC::Map::Buildings::BuildingType; + using OpenSHC::Map::Units::UnitLogicState; + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x00508EC0 + void TileMapState::eraseAreaWithBrush(uint x, uint y, uint brush) + { + uint baseX = x; + if (x > 399) { + return; + } + if (y > 399) { + return; + } + if (DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[y * 400 + x] == 0) { + return; + } + + int brushSize = DAT_TerrainDefinedData::instance.BrushSizeArray[brush]; + uint baseTile = DAT_ViewportRenderState::instance.translationMatrix[y].addXgetTile + x; + /* the original reuses the brush parameter as the saved y and x as the walking tile */ + brush = y; + x = baseTile; + + if (brushSize > 0) { + int index = 0; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getTileForBrush, this)( + 1, index, (int*)&x, (int*)&y, baseTile, brush); + if ((this->LogicLayer[x] & (L_BORDER | L_BORDER_EDGE)) != 0) { + break; + } + int organism = (short)this->OrganismLayer[x]; + if (organism != 0) { + /* tree ids come first, rock ids are biased by 2000 */ + if (organism >= 2000) { + MACRO_CALL_MEMBER(OpenSHC::Map::LandscapeState_Func::removeRock, DAT_LandscapeState::ptr)( + organism - 2000); + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::updateWalkAndPathLayer, + DAT_PathFindingState::ptr)(8, baseX, y); + } else { + MACRO_CALL_MEMBER(OpenSHC::Map::LandscapeState_Func::removeTree, DAT_LandscapeState::ptr)( + organism); + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::updateWalkAndPathLayer, + DAT_PathFindingState::ptr)(3, baseX, y); + } + DAT_PathFindingState::instance.toggleUpdateSeparateAreaTileMap = 1; + DAT_TileMapState::instance.field204_0x554a30 = 1; + } + index++; + } while (index < brushSize); + } + + y = brush; + if (brushSize > 0) { + int index = 0; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getTileForBrush, this)( + 1, index, (int*)&x, (int*)&y, baseTile, brush); + if ((this->LogicLayer[x] & (L_BORDER | L_BORDER_EDGE)) != 0) { + break; + } + this->placementOnWall = 0; + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::validateBuildingPlacementAtTile, this)(0, baseX, y); + if (this->buildingPlacementFail == FALSE) { + if (this->placementOnWall != 0) { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::spawnEraserTileEffect, this)( + 0, DAT_ViewportRenderState::instance.translationMatrix[y].addXgetTile + baseX); + } else if (this->cursorTargetID != 0xffffffff) { + /* razing a keep takes the stockpile with it, and the other way round */ + int owner = DAT_BuildingsState::instance.buildings[this->cursorTargetID].owner; + if (this->cursorTargetID == DAT_GameState::instance.playerDataArray[owner].keep.id + && DAT_GameState::instance.playerDataArray[owner].stockpile.id != 0) { + this->showNoRubbleWhenDestroyingBuilding = 1; + MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::destroyBuildingAndLinkedDuplicates, + DAT_BuildingsState::ptr)(DAT_GameState::instance.playerDataArray[owner].stockpile.id); + } + if (DAT_BuildingsState::instance.buildings[this->cursorTargetID].buildingType + == OpenSHC::Map::Buildings::BT_STOCKPILE + && DAT_GameState::instance.playerDataArray[owner].keep.id != 0) { + this->showNoRubbleWhenDestroyingBuilding = 1; + MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::destroyBuildingAndLinkedDuplicates, + DAT_BuildingsState::ptr)(DAT_GameState::instance.playerDataArray[owner].keep.id); + } + this->showNoRubbleWhenDestroyingBuilding = 1; + MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::destroyBuildingAndLinkedDuplicates, + DAT_BuildingsState::ptr)(this->cursorTargetID); + } + } + index++; + } while (index < brushSize); + } + + y = brush; + if (brushSize > 0) { + int index = 0; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getTileForBrush, this)( + 1, index, (int*)&x, (int*)&y, baseTile, brush); + if ((this->LogicLayer[x] & (L_BORDER | L_BORDER_EDGE)) != 0) { + return; + } + for (int unit = (short)DAT_TileMapState::instance.UnitLayer[x]; unit != 0; + unit = DAT_UnitsState::instance.units[unit].nextUnitOnTheSameTile) { + DAT_UnitsState::instance.units[unit].logicalState = OpenSHC::Map::Units::ULS_REMOVE; + } + index++; + } while (index < brushSize); + } + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/evaluateBuildingPlacementAtCursor.cpp b/src/OpenSHC/Map/TileMapState/evaluateBuildingPlacementAtCursor.cpp new file mode 100644 index 0000000000..024e197546 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/evaluateBuildingPlacementAtCursor.cpp @@ -0,0 +1,228 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" +#include "OpenSHC/Game/GameMode.hpp" +#include "OpenSHC/Game/GameMode2.hpp" +#include "OpenSHC/Map/Buildings/BuildingFailReasonEnum.hpp" +#include "OpenSHC/Map/Buildings/BuildingType.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" +#include "OpenSHC/Globals/DAT_PathFindingState.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_BUILDING; + using OpenSHC::Map::LogicHelpers::L_KEEP_NON_MANOR_HOUSE; + using OpenSHC::Map::LogicHelpers::L_MOAT; + using OpenSHC::Map::LogicHelpers::L_STOCKPILEUnk; + using OpenSHC::Map::LogicHelpers::L_WALL_OR_GATEHOUSE; + + using OpenSHC::Game::GameMode; + using OpenSHC::Game::GameMode2; + using OpenSHC::Map::Buildings::BuildingFailReasonEnum; + using OpenSHC::Map::Buildings::BuildingType; + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x00504A30 + void TileMapState::evaluateBuildingPlacementAtCursor(int playerID, uint x, uint y) + { + uint anchorX = x; + int moatTile = 0; + if (y > 399 || x > 399 || DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[y * 400 + x] == 0) { + this->buildingPlacementFail = TRUE; + return; + } + this->buildingPlacementFail = FALSE; + if (DAT_ViewportRenderState::instance.viewportState.field15_0x3c != 0) { + moatTile = DAT_ViewportRenderState::instance.viewportState.cursorTile; + this->savedCursorTile = DAT_ViewportRenderState::instance.viewportState.cursorTile; + } + + /* the flat view has no ray hit, so the tile under the mouse is used directly */ + uint buildingID; + int wallTile = DAT_ViewportRenderState::instance.viewportState.cursorWallTile; + if (this->flatViewToggleValue1 == 0) { + buildingID = DAT_ViewportRenderState::instance.viewportState.mouseRayBuildingID; + } else { + buildingID = this->BuildingLayer[DAT_ViewportRenderState::instance.viewportState.mouseTile]; + wallTile = 0; + if ((DAT_TileMapState::instance.LogicLayer[DAT_ViewportRenderState::instance.viewportState.mouseTile] + & L_WALL_OR_GATEHOUSE) + != 0 + && ((DAT_TileMapState::instance.LogicLayer[DAT_ViewportRenderState::instance.viewportState.mouseTile] + & L_STOCKPILEUnk) + == 0 + || buildingID == 0)) { + DAT_ViewportRenderState::instance.viewportState.cursorWallTile + = DAT_ViewportRenderState::instance.viewportState.mouseTile; + wallTile = DAT_ViewportRenderState::instance.viewportState.mouseTile; + } + } + if (buildingID != 0) { + anchorX = (short)DAT_BuildingsState::instance.buildings[buildingID].x; + y = (short)DAT_BuildingsState::instance.buildings[buildingID].y; + } + + if (DAT_GameCore::instance.gameMode_2 != OpenSHC::Game::GM_EDITOR + && DAT_GameCore::instance.gameMode_2 != OpenSHC::Game::GM_SIEGE_THAT + && MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::isEnemyTooCloseUnk, + DAT_PathFindingState::ptr)(playerID, anchorX, y, + (-(uint)(DAT_GameSynchronyState::instance.currentGameMode != OpenSHC::Game::GM_SOLITARY) + & 0xfffffff1) + + 0x1e) + != FALSE) { + this->demolishBlocked = 1; + this->buildingPlacementFail = TRUE; + this->buildingPlacementFailReason = (BuildingFailReasonEnum)0x14; + if (buildingID != 0) { + if (DAT_BuildingsState::instance.buildings[buildingID].owner == playerID || playerID == 0) { + this->buildingPlacementFail = TRUE; + this->buildingPlacementFailReason = (BuildingFailReasonEnum)0x14; + this->demolishBlocked = 1; + return; + } + this->buildingPlacementFailReason = OpenSHC::Map::Buildings::BFRE_DEFAULT_CANT_PLACE_THAT_THERE; + return; + } + if (wallTile > 0) { + if ((this->LogicLayer[wallTile] & L_WALL_OR_GATEHOUSE) == 0 + || (this->WallOwnerLayer[wallTile] & 7) + 1 == playerID) { + this->buildingPlacementFail = TRUE; + this->buildingPlacementFailReason = (BuildingFailReasonEnum)0x14; + this->demolishBlocked = 1; + return; + } + this->buildingPlacementFailReason = OpenSHC::Map::Buildings::BFRE_DEFAULT_CANT_PLACE_THAT_THERE; + return; + } + if (moatTile > 0 && (this->LogicLayer[moatTile] & L_MOAT) != 0) { + int moatID = MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::returnOwnedMoatAtTile, this)(moatTile); + if (moatID == 0) { + return; + } + if (DAT_GameState::instance.mapAndTime.playerTeams[this->moats[moatID].owner] + == DAT_GameState::instance.mapAndTime.playerTeams[playerID]) { + return; + } + } + this->buildingPlacementFailReason = OpenSHC::Map::Buildings::BFRE_DEFAULT_CANT_PLACE_THAT_THERE; + return; + } + + if (DAT_ViewportRenderState::instance.viewportState.somePitchDitchID != 0) { + if (this->pitchDitches[DAT_ViewportRenderState::instance.viewportState.somePitchDitchID].owner + != DAT_GameSynchronyState::instance.currentPlayerSlotID) { + this->buildingPlacementFail = TRUE; + return; + } + this->cursorTargetID = -DAT_ViewportRenderState::instance.viewportState.somePitchDitchID; + return; + } + + if ((int)buildingID < 1 + || (DAT_BuildingsState::instance.buildings[buildingID].owner != playerID && playerID != 0)) { + this->buildingPlacementFail = TRUE; + } + + bool checkMoat = true; + if (wallTile > 0) { + /* a stockpile tile carries the wall flag too, but nothing may be built on it */ + if ((this->LogicLayer[wallTile] & L_WALL_OR_GATEHOUSE) != 0 + && (this->LogicLayer[wallTile] & L_STOCKPILEUnk) != 0) { + this->buildingPlacementFail = TRUE; + return; + } + if ((this->LogicLayer[wallTile] & L_WALL_OR_GATEHOUSE) != 0 && this->BuildingLayer[wallTile] == 0 + && this->placementOnMoat == 0) { + if ((this->WallOwnerLayer[wallTile] & 7) + 1 != playerID) { + return; + } + this->buildingPlacementFail = FALSE; + this->placementOnWall = 1; + if ((this->MiscDisplayLayer[wallTile] & 0x400) != 0) { + this->buildingPlacementFail = TRUE; + } + checkMoat = false; + } + } + if (checkMoat) { + if (moatTile < 1 || (this->LogicLayer[moatTile] & L_MOAT) == 0 || buildingID != 0) { + if (this->placementOnWall != 0 || this->placementOnMoat != 0) { + this->buildingPlacementFail = TRUE; + } + } else if (this->placementOnWall == 0) { + int moatID = MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::returnOwnedMoatAtTile, this)(moatTile); + if (moatID == 0) { + return; + } + if (DAT_GameState::instance.mapAndTime.playerTeams[this->moats[moatID].owner] + != DAT_GameState::instance.mapAndTime.playerTeams[playerID]) { + return; + } + this->placementOnMoat = 1; + this->buildingPlacementFail = (BOOLEnum)((this->MiscDisplayLayer[moatTile] & 0x400) != 0); + wallTile = moatTile; + } else { + this->buildingPlacementFail = TRUE; + } + } + + if (wallTile > 0 && this->UnitLayer[wallTile] != 0) { + this->buildingPlacementFail = TRUE; + } + if (buildingID != 0) { + if (DAT_GameCore::instance.gameMode_2 != OpenSHC::Game::GM_EDITOR) { + if (DAT_GameCore::instance.gameMode_2 == OpenSHC::Game::GM_SIEGE_THAT) { + if (DAT_BuildingsState::instance.buildings[buildingID].buildingType + == OpenSHC::Map::Buildings::BT_SIGNPOST) { + this->buildingPlacementFail = TRUE; + } + } else { + switch (DAT_BuildingsState::instance.buildings[buildingID].buildingType) { + case OpenSHC::Map::Buildings::BT_UNKNOWN1: + case OpenSHC::Map::Buildings::BT_MANORHOUSE: + case OpenSHC::Map::Buildings::BT_STONEKEEP: + case OpenSHC::Map::Buildings::BT_STRONGHOLD: + case OpenSHC::Map::Buildings::BT_SIGNPOST: + case OpenSHC::Map::Buildings::BT_CAMPGROUND: + case OpenSHC::Map::Buildings::BT_KEEPDOOR_LEFT: + case OpenSHC::Map::Buildings::BT_KEEPDOOR_RIGHT: + case OpenSHC::Map::Buildings::BT_KEEPDOOR: + case OpenSHC::Map::Buildings::BT_POND: + this->buildingPlacementFail = TRUE; + } + } + } + if ((int)buildingID < 0) { + this->cursorTargetID = buildingID; + return; + } + } + + if ((this->LogicLayer[DAT_BuildingsState::instance.buildings[buildingID].currentTilePositionAdjusted] + & (L_BUILDING | L_KEEP_NON_MANOR_HOUSE)) + == 0 + && DAT_BuildingsState::instance.buildings[buildingID].buildingType + != OpenSHC::Map::Buildings::BT_GATEHOUSELARGE + && DAT_BuildingsState::instance.buildings[buildingID].buildingType + != OpenSHC::Map::Buildings::BT_GATEHOUSESMALL + && DAT_BuildingsState::instance.buildings[buildingID].buildingType != OpenSHC::Map::Buildings::BT_WOODGATE1 + && DAT_BuildingsState::instance.buildings[buildingID].buildingType != OpenSHC::Map::Buildings::BT_WOODGATE2 + && DAT_BuildingsState::instance.buildings[buildingID].buildingType != OpenSHC::Map::Buildings::BT_KEEPDOOR + && DAT_BuildingsState::instance.buildings[buildingID].buildingType != OpenSHC::Map::Buildings::BT_DRAWBRIDGE + && DAT_BuildingsState::instance.buildings[buildingID].buildingType != OpenSHC::Map::Buildings::BT_KILLINGPIT + && this->placementOnWall == 0 && this->placementOnMoat == 0) { + this->buildingPlacementFail = TRUE; + } + this->cursorTargetID = buildingID; + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/findNearestFriendlyMoatTileForDigging.cpp b/src/OpenSHC/Map/TileMapState/findNearestFriendlyMoatTileForDigging.cpp new file mode 100644 index 0000000000..d73728b4bf --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/findNearestFriendlyMoatTileForDigging.cpp @@ -0,0 +1,104 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Map/Navigation/DirectionAlgorithmState.func.hpp" +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +#include "OpenSHC/Globals/DAT_DirectionAlgorithmState.hpp" +#include "OpenSHC/Globals/DAT_GameState.hpp" +#include "OpenSHC/Globals/DAT_GameSynchronyState.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_UnitsState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_MOAT; + using OpenSHC::Map::LogicHelpers::L_MOAT_DUG_OR_PLANNED; + + using OpenSHC::Map::LogicHelpers::L_MOAT; + using OpenSHC::Map::LogicHelpers::L_MOAT_DUG_OR_PLANNED; + + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x005111D0 + BOOLEnum TileMapState::findNearestFriendlyMoatTileForDigging(int playerID, int unitID, int number) + { + int unitX = DAT_UnitsState::instance.units[unitID].x; + int unitY = DAT_UnitsState::instance.units[unitID].y; + ushort area + = this->PathConnectionLayer[DAT_ViewportRenderState::instance.translationMatrix[unitY].addXgetTile + unitX]; + int best = 1000; + BOOLEnum bestMoatID = ~FALSE; + if (0 < this->currentMoatCount) { + for (int moatID = 0; moatID < this->currentMoatCount; moatID++) { + /* digging works on own moat, filling in works on anyone else's */ + if (number == 1 + && DAT_GameState::instance.mapAndTime.playerTeams[this->moats[moatID].owner] + != DAT_GameState::instance.mapAndTime.playerTeams[playerID]) { + continue; + } + if (number == 2 + && DAT_GameState::instance.mapAndTime.playerTeams[this->moats[moatID].owner] + == DAT_GameState::instance.mapAndTime.playerTeams[playerID]) { + continue; + } + if (this->moats[moatID].stage != number) { + continue; + } + int tile = this->moats[moatID].tile; + if (this->BuildingLayer[tile] != 0 && this->moats[moatID].zeroOrTwo == 0) { + continue; + } + if ((this->LogicLayer[tile] & (L_MOAT_DUG_OR_PLANNED | L_MOAT)) == 0) { + continue; + } + if (this->moats[moatID].someCountDown >= 'd') { + continue; + } + if (this->UnitLayer[tile] != 0 + && DAT_UnitsState::instance.units[this->UnitLayer[tile]].someUnitStat4 == 0) { + continue; + } + if (number == 2 + && MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::findTileInSameAreaAndNoTooHeightDifference, + this)(area, tile, this->moats[moatID].y) + == FALSE) { + continue; + } + + byte pathCost + = DAT_TileMapState::instance.SEC_PathfindingCostTileMap1105[this->moats[moatID].owner][tile]; + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::DirectionAlgorithmState_Func::setAxisBasedDistanceResult, + DAT_DirectionAlgorithmState::ptr)(unitX, unitY, this->moats[moatID].x, this->moats[moatID].y); + int score = DAT_DirectionAlgorithmState::instance.distanceHigh; + int fromTarget; + if (DAT_UnitsState::instance.units[unitID].targetX < 1) { + fromTarget = 0; + } else { + fromTarget = MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::DirectionAlgorithmState_Func::setAxisBasedDistanceResult, + DAT_DirectionAlgorithmState::ptr)(DAT_UnitsState::instance.units[unitID].targetX, + DAT_UnitsState::instance.units[unitID].targetY, this->moats[moatID].x, this->moats[moatID].y); + } + if (DAT_GameSynchronyState::instance.currentPlayerFullIDArray[playerID] == -1) { + score = score + pathCost * 10; + } + score = fromTarget / 2 + this->moats[moatID].someCountDown + score; + if (score < best) { + bestMoatID = moatID; + best = score; + } + } + + if (bestMoatID == FALSE) { + return FALSE; + } + } + /* bug:fixme: with no moats at all the original indexes moats[-1] here */ + this->moats[bestMoatID].someCountDown = this->moats[bestMoatID].someCountDown + 20; + return bestMoatID; + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/findNearestValidDigTileNearTarget.cpp b/src/OpenSHC/Map/TileMapState/findNearestValidDigTileNearTarget.cpp new file mode 100644 index 0000000000..0c5eaf431c --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/findNearestValidDigTileNearTarget.cpp @@ -0,0 +1,79 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Map/Buildings/BuildingsState.func.hpp" +#include "OpenSHC/Map/Navigation/DirectionAlgorithmState.func.hpp" + +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_DirectionAlgorithmState.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + + // FUNCTION: STRONGHOLDCRUSADER 0x00500980 + undefined4 TileMapState::findNearestValidDigTileNearTarget(uint x1, uint y1, uint x2, uint y2) + { + if (x1 > 399 || y1 > 399) { + return 0; + } + if (DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[y1 * 400 + x1] == 0) { + return 0; + } + if (x2 > 399 || y2 > 399) { + return 0; + } + if (DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[y2 * 400 + x2] == 0) { + return 0; + } + + int area = (short)this + ->PathConnectionLayer[DAT_ViewportRenderState::instance.translationMatrix[y1].addXgetTile + x1]; + int targetTile = DAT_ViewportRenderState::instance.translationMatrix[y2].addXgetTile + x2; + uint targetHeight = this->HeightLayer[targetTile]; + int bestDistance = 10000; + int bestIndex = -1; + int targetBuildingID = this->BuildingLayer[targetTile]; + if (targetBuildingID != 0) { + targetHeight = targetHeight + + MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::getBuildingHeightForBuildingID, + DAT_BuildingsState::ptr)(targetBuildingID); + } + + for (int index = 0; index < 4; index++) { + int fromXPosition = DAT_TerrainDefinedData::instance.field2347_0x378c[index].x + x2; + int fromYPosition = DAT_TerrainDefinedData::instance.field2347_0x378c[index].y + y2; + int tile = DAT_ViewportRenderState::instance.translationMatrix[fromYPosition].addXgetTile + fromXPosition; + if ((short)this->PathConnectionLayer[tile] != area) { + continue; + } + uint height = this->HeightLayer[tile]; + int buildingID = this->BuildingLayer[tile]; + if (buildingID != 0) { + height = height + + MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::getBuildingHeightForBuildingID, + DAT_BuildingsState::ptr)(buildingID); + } + if ((int)height >= (int)(targetHeight + 0x10) || (int)(targetHeight - 0x10) >= (int)height) { + continue; + } + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::DirectionAlgorithmState_Func::setAxisBasedDistanceResult, + DAT_DirectionAlgorithmState::ptr)(x1, y1, fromXPosition, fromYPosition); + if (DAT_DirectionAlgorithmState::instance.distanceHigh < bestDistance) { + bestDistance = DAT_DirectionAlgorithmState::instance.distanceHigh; + bestIndex = index; + } + } + + if (bestIndex >= 0) { + this->field155_0x5549a8 = DAT_TerrainDefinedData::instance.field2347_0x378c[bestIndex].x + x2; + this->field156_0x5549ac = DAT_TerrainDefinedData::instance.field2347_0x378c[bestIndex].y + y2; + return 1; + } + this->field155_0x5549a8 = x2; + this->field156_0x5549ac = y2; + return 0; + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/findTileInSameAreaAndNoTooHeightDifference.cpp b/src/OpenSHC/Map/TileMapState/findTileInSameAreaAndNoTooHeightDifference.cpp new file mode 100644 index 0000000000..1fb3dd439d --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/findTileInSameAreaAndNoTooHeightDifference.cpp @@ -0,0 +1,27 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x00500370 + BOOLEnum TileMapState::findTileInSameAreaAndNoTooHeightDifference(int area, int tile, int yUnk) + { + for (int attempts = 0; attempts < 8; attempts++) { + int neighbour = this->directionTranslationMatrix[yUnk][attempts] + tile; + if (this->HeightLayer[neighbour] > this->HeightLayer[tile] + 16) { + continue; + } + if ((short)this->PathConnectionLayer[neighbour] != area) { + continue; + } + return TRUE; + } + return FALSE; + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/floodMoatUnderRemovedBuilding.cpp b/src/OpenSHC/Map/TileMapState/floodMoatUnderRemovedBuilding.cpp new file mode 100644 index 0000000000..733e8a9375 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/floodMoatUnderRemovedBuilding.cpp @@ -0,0 +1,46 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" + +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_PathFindingState.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_MOAT; + + // FUNCTION: STRONGHOLDCRUSADER 0x00508910 + void TileMapState::floodMoatUnderRemovedBuilding(int buildingID) + { + uint yPosition = DAT_BuildingsState::instance.buildings[buildingID].y; + uint xPosition = DAT_BuildingsState::instance.buildings[buildingID].x; + uint widthOrHeight = DAT_BuildingsState::instance.buildings[buildingID].widthOrHeight; + int variation = DAT_BuildingsState::instance.buildings[buildingID].buildingVariation / 2; + int buildingSizeTileIndex = 0; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)( + buildingSizeTileIndex, 5); + int targetedTile + = DAT_ViewportRenderState::instance.translationMatrix[this->buildingY + yPosition].addXgetTile + + this->buildingX + xPosition; + if (DAT_TerrainDefinedData::instance.DrawbridgeOrientationMapping[variation][buildingSizeTileIndex] != 0) { + if (MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::returnOwnedMoatAtTile, this)(targetedTile) + != 0) { + this->LogicLayer[targetedTile] = this->LogicLayer[targetedTile] | L_MOAT; + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::setMoatVisualStateAtTile, this)(targetedTile, 2); + } + } + buildingSizeTileIndex++; + } while (buildingSizeTileIndex < this->constructionTileCount); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::updateBuildingGraphicsLayer, this)(buildingID); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::updatePathLinkagesForBuilding, this)(buildingID); + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::updateWalkAndPathLayer, + DAT_PathFindingState::ptr)(widthOrHeight + 6, xPosition, yPosition); + DAT_PathFindingState::instance.toggleUpdateSeparateAreaTileMap = 1; + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/generateDustClouds.cpp b/src/OpenSHC/Map/TileMapState/generateDustClouds.cpp new file mode 100644 index 0000000000..84b7afe86c --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/generateDustClouds.cpp @@ -0,0 +1,69 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Map/Entities/EntityState.func.hpp" +#include "OpenSHC/Random/RNG.func.hpp" +#include "OpenSHC/Map/Entities/EntityType.hpp" + +#include "OpenSHC/Globals/DAT_EntityState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" +#include "OpenSHC/Globals/SEC_RNG.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::Entities::EntityType; + + // FUNCTION: STRONGHOLDCRUSADER 0x004FC490 + void TileMapState::generateDustClouds() + { + short seed = SEC_RNG::instance.currentNumber2; + int random = SEC_RNG::instance.currentNumber2; + MACRO_CALL_MEMBER(OpenSHC::Random::RNG_Func::nextRandomNumber2, SEC_RNG::ptr)(); + this->SEC_Section1052 = this->SEC_Section1052 + 1; + if (random % 500 == this->SEC_Section1052 % 500) { + this->SEC_Section1053 = random % 0xb4; + } + if (random % 0x4b0 == this->SEC_Section1052 % 0x4b0) { + this->SEC_Section1054 = random % 0xb4; + } + if (this->SEC_Section1053 != 0) { + this->SEC_Section1053 = this->SEC_Section1053 - 1; + } + if (this->SEC_Section1054 != 0) { + this->SEC_Section1054 = this->SEC_Section1054 - 1; + } + + for (int i = 0; i < this->temporaryTerrainTypeIndex; i++) { + int tile = this->temporaryTerrainTypeArray[i]; + /* one tile out of every 64 puffs, selected by the tile's own random value */ + if ((short)(this->RandomLayer[tile] ^ seed) % 64 != this->SEC_Section1052 % 64) { + continue; + } + int stage = this->temporaryTerrainTypeBinaryArray[i]; + if (stage == 0) { + if (this->SEC_Section1054 != 0) { + continue; + } + } else { + if (this->SEC_Section1053 != 0) { + continue; + } + if (stage != 1) { + stage = 2; + } + } + MACRO_CALL_MEMBER(OpenSHC::Map::Entities::EntityState_Func::spawnProjectileEntity, DAT_EntityState::ptr)(0, + 0, 0, + (tile + - DAT_ViewportRenderState::instance + .translationMatrix[DAT_ViewportRenderState::instance.tileTranslationMatrix_YComponent[tile]] + .addXgetTile) + * 8 + + 4, + DAT_ViewportRenderState::instance.tileTranslationMatrix_YComponent[tile] * 8 + 4, + this->HeightLayer[tile], 0, 0, 0, OpenSHC::Map::Entities::ET_DUST_CLOUD, stage); + } + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/getBuildingHurtSFXID.cpp b/src/OpenSHC/Map/TileMapState/getBuildingHurtSFXID.cpp new file mode 100644 index 0000000000..1fb7d06de6 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/getBuildingHurtSFXID.cpp @@ -0,0 +1,57 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Map/Buildings/BuildingLogicalState.hpp" + +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::Buildings::BuildingLogicalState; + + // FUNCTION: STRONGHOLDCRUSADER 0x004F8210 + uint TileMapState::getBuildingHurtSFXID(int tileUnk) + { + short buildingID = this->BuildingLayer[tileUnk]; + if (buildingID != 0) { + if (DAT_BuildingsState::instance.buildings[buildingID].logicalState == 0) { + return 0; + } + if (DAT_BuildingsState::instance.buildings[buildingID].logicalState == OpenSHC::Map::Buildings::BLS_REMOVE) { + return 0; + } + if (DAT_BuildingsState::instance.buildings[buildingID].currentHealth == 0) { + return 0; + } + + switch (DAT_BuildingsState::instance.buildings[buildingID].buildingType) { + case OpenSHC::Map::Buildings::BT_BARRACKS: + case OpenSHC::Map::Buildings::BT_STOCKPILE: + case OpenSHC::Map::Buildings::BT_ARMORY: + case OpenSHC::Map::Buildings::BT_ENGINEERSGUILD: + case OpenSHC::Map::Buildings::BT_TUNNELERSGUILD: + case OpenSHC::Map::Buildings::BT_CHAPEL: + case OpenSHC::Map::Buildings::BT_CHURCH: + case OpenSHC::Map::Buildings::BT_CATHEDRAL: + case OpenSHC::Map::Buildings::BT_MANORHOUSE: + case OpenSHC::Map::Buildings::BT_STONEKEEP: + case OpenSHC::Map::Buildings::BT_STRONGHOLD: + case OpenSHC::Map::Buildings::BT_GATEHOUSELARGE: + case OpenSHC::Map::Buildings::BT_GATEHOUSESMALL: + case OpenSHC::Map::Buildings::BT_GATEHOUSE: + 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_OUTPOST_EUROPEAN: + return 2; + default: + return 1; + } + } + return (uint)this->LogicLayer[tileUnk] >> 7 & 2; + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/getBuildingSizeForCommandBuildingType.cpp b/src/OpenSHC/Map/TileMapState/getBuildingSizeForCommandBuildingType.cpp new file mode 100644 index 0000000000..40d0882864 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/getBuildingSizeForCommandBuildingType.cpp @@ -0,0 +1,223 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Commands/MappersEnum.hpp" + +#include "OpenSHC/Globals/DAT_TileMapState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Commands::MappersEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x004FA550 + int TileMapState::getBuildingSizeForCommandBuildingType(MappersEnum commandBuildingType) + { + /* + The original dispatches through a byte index table at 0x004FA614 (0x147 entries, biased by + M_MAPPER_UNDUGMOAT) into a jump table at 0x004FA5DC, which is what MSVC emits for a dense + switch; Ghidra could not normalise it and rendered the dispatch as a read through an + unnamed pointer array. The case groups below are that byte table, decoded. + + field159_0x5549b8 is written through the global instance, not through this, which is how + the original addresses it. + */ + switch (commandBuildingType) { + case OpenSHC::Commands::M_MAPPER_FLETCHER: + case OpenSHC::Commands::M_MAPPER_HOVEL: + case OpenSHC::Commands::M_MAPPER_BAKER: + case OpenSHC::Commands::M_MAPPER_BREWER: + case OpenSHC::Commands::M_MAPPER_GRANARY: + case OpenSHC::Commands::M_MAPPER_ARMOURY: + case OpenSHC::Commands::M_MAPPER_POLETURNER: + case OpenSHC::Commands::M_MAPPER_BLACKSMITH: + case OpenSHC::Commands::M_MAPPER_ARMOURER: + case OpenSHC::Commands::M_MAPPER_TANNER: + case OpenSHC::Commands::M_MAPPER_IRON_MINE: + case OpenSHC::Commands::M_MAPPER_PITCH_WORKINGS: + case OpenSHC::Commands::M_MAPPER_TOWER2: + case OpenSHC::Commands::M_MAPPER_GARDEN10: + case OpenSHC::Commands::M_MAPPER_GARDEN11: + case OpenSHC::Commands::M_MAPPER_GARDEN12: + case OpenSHC::Commands::M_MAPPER_OIL_SMELTER: + case (MappersEnum)258: + case (MappersEnum)259: + case (MappersEnum)260: + case OpenSHC::Commands::M_MAPPER_WATERPOT: + return 4; + case OpenSHC::Commands::M_MAPPER_STORES: + case OpenSHC::Commands::M_MAPPER_TRADEPOST: + case OpenSHC::Commands::M_MAPPER_BARRACKS_EURO: + case OpenSHC::Commands::M_MAPPER_BARRACKS_ARAB: + case OpenSHC::Commands::M_MAPPER_ENGINEERS_GUILD: + case OpenSHC::Commands::M_MAPPER_TUNNELERS_GUILD: + case OpenSHC::Commands::M_MAPPER_INN: + case OpenSHC::Commands::M_MAPPER_GATE_INNER: + case OpenSHC::Commands::M_MAPPER_DRAWBRIDGE: + case OpenSHC::Commands::M_MAPPER_TOWER3: + case OpenSHC::Commands::M_MAPPER_GATE_STONE1A: + case OpenSHC::Commands::M_MAPPER_GATE_STONE1B: + case OpenSHC::Commands::M_MAPPER_OUTPOST_EURO: + case OpenSHC::Commands::M_MAPPER_OUTPOST_ARAB: + case OpenSHC::Commands::M_MAPPER_CESS_PIT1: + case OpenSHC::Commands::M_MAPPER_CESS_PIT2: + case OpenSHC::Commands::M_MAPPER_CESS_PIT3: + case OpenSHC::Commands::M_MAPPER_CESS_PIT4: + case OpenSHC::Commands::M_MAPPER_DUNGEON: + case OpenSHC::Commands::M_MAPPER_DUNKING_STOOL: + case OpenSHC::Commands::M_MAPPER_DANCING_BEAR: + case OpenSHC::Commands::M_MAPPER_POND1: + case OpenSHC::Commands::M_MAPPER_POND2_SMALL: + return 5; + case OpenSHC::Commands::M_MAPPER_QUARRY: + case OpenSHC::Commands::M_MAPPER_STABLES: + case OpenSHC::Commands::M_MAPPER_HEALER: + case OpenSHC::Commands::M_MAPPER_CHURCH1: + case OpenSHC::Commands::M_MAPPER_TOWER4: + case OpenSHC::Commands::M_MAPPER_TOWER5: + case OpenSHC::Commands::M_MAPPER_POND3_LARGE1: + case OpenSHC::Commands::M_MAPPER_POND4_LARGE2: + return 6; + case OpenSHC::Commands::M_MAPPER_WOODSMAN: + case OpenSHC::Commands::M_MAPPER_TUNNEL: + case OpenSHC::Commands::M_MAPPER_TUNNEL_CONSTRUCTION: + case OpenSHC::Commands::M_MAPPER_MILL: + case OpenSHC::Commands::M_MAPPER_HUNTER: + case OpenSHC::Commands::M_MAPPER_TOWER1: + case OpenSHC::Commands::M_MAPPER_GATE_WOOD1A: + case OpenSHC::Commands::M_MAPPER_GATE_WOOD1B: + case OpenSHC::Commands::M_MAPPER_GATE_WOOD1C: + case OpenSHC::Commands::M_MAPPER_GATE_WOOD1D: + case OpenSHC::Commands::M_MAPPER_GARDEN7: + case OpenSHC::Commands::M_MAPPER_GARDEN8: + case OpenSHC::Commands::M_MAPPER_GARDEN9: + case OpenSHC::Commands::M_MAPPER_MAYPOLE: + case OpenSHC::Commands::M_MAPPER_STOCKS: + case OpenSHC::Commands::M_MAPPER_CATAPULT: + case OpenSHC::Commands::M_MAPPER_TREBUCHET: + case OpenSHC::Commands::M_MAPPER_SIEGE_TOWER: + case OpenSHC::Commands::M_MAPPER_BATTERING_RAM: + case OpenSHC::Commands::M_MAPPER_PORTABLE_SHIELD: + case OpenSHC::Commands::M_MAPPER_BURNING_STAKE: + case OpenSHC::Commands::M_MAPPER_RACK_STRETCHING: + case OpenSHC::Commands::M_MAPPER_CHOPPING_BLOCK: + case OpenSHC::Commands::M_MAPPER_DOG_CAGE: + case OpenSHC::Commands::M_MAPPER_WELL: + case OpenSHC::Commands::M_MAPPER_ARAB_BALLISTA: + return 3; + case OpenSHC::Commands::M_MAPPER_KEEP1: + case OpenSHC::Commands::M_MAPPER_KEEP2: + case OpenSHC::Commands::M_MAPPER_GATE_MAIN: + case OpenSHC::Commands::M_MAPPER_GATE_STONE2A: + case OpenSHC::Commands::M_MAPPER_GATE_STONE2B: + return 7; + case OpenSHC::Commands::M_MAPPER_CAMP_FIRE: + case OpenSHC::Commands::M_MAPPER_KILLING_PIT: + case OpenSHC::Commands::M_MAPPER_PITCH_DITCH: + case (MappersEnum)248: + case (MappersEnum)249: + case (MappersEnum)250: + case (MappersEnum)251: + case OpenSHC::Commands::M_MAPPER_SHRINE5: + return 1; + case OpenSHC::Commands::M_MAPPER_KEEP3: + case OpenSHC::Commands::M_MAPPER_APPLEFARM: + return 0xb; + case OpenSHC::Commands::M_MAPPER_WHEATFARM: + case OpenSHC::Commands::M_MAPPER_HOPSFARM: + case OpenSHC::Commands::M_MAPPER_CHURCH2: + return 9; + case OpenSHC::Commands::M_MAPPER_CHURCH3: + return 0xd; + case OpenSHC::Commands::M_MAPPER_CATTLEFARM: + return 0xa; + case OpenSHC::Commands::M_MAPPER_UNDUGMOAT: + case OpenSHC::Commands::M_MAPPER_DUGMOAT: + case OpenSHC::Commands::M_MAPPER_MOAT: + case OpenSHC::Commands::M_MAPPER_ANTIMOAT: + DAT_TileMapState::instance.field159_0x5549b8 = 1; + return 2; + case OpenSHC::Commands::M_MAPPER_OXENBASE: + case OpenSHC::Commands::M_MAPPER_SIGNPOST: + case OpenSHC::Commands::M_MAPPER_GATE_POSTERN: + case OpenSHC::Commands::M_MAPPER_GARDEN1: + case OpenSHC::Commands::M_MAPPER_GARDEN2: + case OpenSHC::Commands::M_MAPPER_GARDEN3: + case OpenSHC::Commands::M_MAPPER_GARDEN4: + case OpenSHC::Commands::M_MAPPER_GARDEN5: + case OpenSHC::Commands::M_MAPPER_GARDEN6: + case OpenSHC::Commands::M_MAPPER_GALLOWS: + case (MappersEnum)252: + case (MappersEnum)253: + case (MappersEnum)254: + case (MappersEnum)255: + case (MappersEnum)256: + case (MappersEnum)257: + case OpenSHC::Commands::M_MAPPER_GIBBET: + case OpenSHC::Commands::M_MAPPER_STATUE1: + case OpenSHC::Commands::M_MAPPER_STATUE2: + case OpenSHC::Commands::M_MAPPER_STATUE3: + case OpenSHC::Commands::M_MAPPER_STATUE4: + case OpenSHC::Commands::M_MAPPER_STATUE5: + case OpenSHC::Commands::M_MAPPER_SHRINE1: + case OpenSHC::Commands::M_MAPPER_SHRINE2: + case OpenSHC::Commands::M_MAPPER_SHRINE3: + case OpenSHC::Commands::M_MAPPER_SHRINE4: + return 2; + case OpenSHC::Commands::M_MAPPER_FLAG_TYPE0: + case OpenSHC::Commands::M_MAPPER_FLAG_TYPE1: + case OpenSHC::Commands::M_MAPPER_FLAG_TYPE2: + case OpenSHC::Commands::M_MAPPER_FLAG_TYPE3: + case OpenSHC::Commands::M_MAPPER_HEADS: + case OpenSHC::Commands::M_MAPPER_BRAZIER: + case OpenSHC::Commands::M_MAPPER_MANGONEL: + case OpenSHC::Commands::M_MAPPER_BALLISTA: + case OpenSHC::Commands::M_MAPPER_PEOPLE_ARCHERS: + case OpenSHC::Commands::M_MAPPER_PEOPLE_SPEARMEN: + case OpenSHC::Commands::M_MAPPER_PEOPLE_PIKEMEN: + case OpenSHC::Commands::M_MAPPER_PEOPLE_MACEMEN: + case OpenSHC::Commands::M_MAPPER_PEOPLE_XBOWMEN: + case OpenSHC::Commands::M_MAPPER_PEOPLE_SWORDSMEN: + case OpenSHC::Commands::M_MAPPER_PEOPLE_KNIGHTS: + case OpenSHC::Commands::M_MAPPER_PEOPLE_LADDERMEN: + case OpenSHC::Commands::M_MAPPER_PEOPLE_ENGINEERS: + case OpenSHC::Commands::M_MAPPER_PEOPLE_ENGINEERS_POTS: + case OpenSHC::Commands::M_MAPPER_PEOPLE_MONKS: + case OpenSHC::Commands::M_MAPPER_PEOPLE_CATAPULTS: + case OpenSHC::Commands::M_MAPPER_PEOPLE_TREBUCHETS: + case OpenSHC::Commands::M_MAPPER_PEOPLE_BATTERING_RAMS: + case OpenSHC::Commands::M_MAPPER_PEOPLE_SIEGE_TOWERS: + case OpenSHC::Commands::M_MAPPER_PEOPLE_PORTABLE_SHIELDS: + case OpenSHC::Commands::M_MAPPER_PEOPLE_TUNNELERS: + case OpenSHC::Commands::M_MAPPER_PLACE_ASSEMBLY_POINT1: + case OpenSHC::Commands::M_MAPPER_PLACE_ASSEMBLY_POINT2: + case OpenSHC::Commands::M_MAPPER_PLACE_ASSEMBLY_POINT3: + case OpenSHC::Commands::M_MAPPER_PLACE_ASSEMBLY_POINT4: + case OpenSHC::Commands::M_MAPPER_PLACE_ASSEMBLY_POINT5: + case OpenSHC::Commands::M_MAPPER_PLACE_ASSEMBLY_POINT6: + case OpenSHC::Commands::M_MAPPER_PLACE_ASSEMBLY_POINT7: + case OpenSHC::Commands::M_MAPPER_PEOPLE_ARAB_BOW: + case OpenSHC::Commands::M_MAPPER_PEOPLE_ARAB_SLAVE: + case OpenSHC::Commands::M_MAPPER_PEOPLE_ARAB_SLINGER: + case OpenSHC::Commands::M_MAPPER_PEOPLE_ARAB_ASSASIN: + case OpenSHC::Commands::M_MAPPER_PEOPLE_ARAB_HORSEMAN: + case OpenSHC::Commands::M_MAPPER_PEOPLE_ARAB_SWORDSMAN: + case OpenSHC::Commands::M_MAPPER_PEOPLE_ARAB_GRENADIER: + case OpenSHC::Commands::M_MAPPER_PEOPLE_ARAB_BALLISTA: + case OpenSHC::Commands::M_MAPPER_PLACE_ASSEMBLY_POINTM1: + case OpenSHC::Commands::M_MAPPER_PLACE_ASSEMBLY_POINTM2: + case OpenSHC::Commands::M_MAPPER_PLACE_ASSEMBLY_POINTM3: + case OpenSHC::Commands::M_MAPPER_PLACE_ASSEMBLY_POINTM4: + case OpenSHC::Commands::M_MAPPER_PLACE_ASSEMBLY_POINTM5: + case OpenSHC::Commands::M_MAPPER_PLACE_ASSEMBLY_POINTM6: + case OpenSHC::Commands::M_MAPPER_PLACE_ASSEMBLY_POINTM7: + case OpenSHC::Commands::M_MAPPER_PLACE_ASSEMBLY_POINTE1: + case OpenSHC::Commands::M_MAPPER_PLACE_ASSEMBLY_POINTE2: + case OpenSHC::Commands::M_MAPPER_PLACE_ASSEMBLY_POINTT1: + case OpenSHC::Commands::M_MAPPER_PLACE_ASSEMBLY_POINTK1: + return 0; + } + return -1; + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/getBuildingSizeIndexMappingData.cpp b/src/OpenSHC/Map/TileMapState/getBuildingSizeIndexMappingData.cpp new file mode 100644 index 0000000000..0912b24d0c --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/getBuildingSizeIndexMappingData.cpp @@ -0,0 +1,35 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Globals/DAT_BuildingSizeIndexMapping.hpp" + +namespace OpenSHC { +namespace Map { + + // FUNCTION: STRONGHOLDCRUSADER 0x004F9880 + void TileMapState::getBuildingSizeIndexMappingData(int buildingSizeTileIndex, int buildingWidthOrHeight) + { + this->constructionTileCount = buildingWidthOrHeight * buildingWidthOrHeight; + this->buildingX = DAT_BuildingSizeIndexMapping::instance[buildingWidthOrHeight][buildingSizeTileIndex][0]; + this->buildingY = DAT_BuildingSizeIndexMapping::instance[buildingWidthOrHeight][buildingSizeTileIndex][1]; + switch (this->mapOrientation) { + case 0: + this->buildingRotationRelatedValue + = DAT_BuildingSizeIndexMapping::instance[buildingWidthOrHeight][buildingSizeTileIndex][2]; + return; + case 2: + this->buildingRotationRelatedValue + = DAT_BuildingSizeIndexMapping::instance[buildingWidthOrHeight][buildingSizeTileIndex][3]; + return; + case 4: + this->buildingRotationRelatedValue + = DAT_BuildingSizeIndexMapping::instance[buildingWidthOrHeight][buildingSizeTileIndex][4]; + return; + case 6: + this->buildingRotationRelatedValue + = DAT_BuildingSizeIndexMapping::instance[buildingWidthOrHeight][buildingSizeTileIndex][5]; + } + return; + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/getCastleBuildRangeForMapSize.cpp b/src/OpenSHC/Map/TileMapState/getCastleBuildRangeForMapSize.cpp new file mode 100644 index 0000000000..56763b7058 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/getCastleBuildRangeForMapSize.cpp @@ -0,0 +1,25 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Map/MapConstants.hpp" + +namespace OpenSHC { +namespace Map { + + // FUNCTION: STRONGHOLDCRUSADER 0x004FBC30 + undefined4 TileMapState::getCastleBuildRangeForMapSize() + { + switch (this->mapSize) { + case 160: + return 45; + case 200: + return 50; + case 300: + return 60; + case MC_MAP_XY_LIMIT: + return 70; + } + return 70; + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/getHeightAtTileIncludingOwnersBuildings.cpp b/src/OpenSHC/Map/TileMapState/getHeightAtTileIncludingOwnersBuildings.cpp new file mode 100644 index 0000000000..1cc335ad53 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/getHeightAtTileIncludingOwnersBuildings.cpp @@ -0,0 +1,86 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_WALL_OR_GATEHOUSE; + + // FUNCTION: STRONGHOLDCRUSADER 0x004FFF10 + uint TileMapState::getHeightAtTileIncludingOwnersBuildings(int tile, int playerID) + { + /* + The early layer reads go through the global instance's absolute address, while the + BuildingLayer reads inside the switch arms go through this; follow each one separately. + */ + if (DAT_TileMapState::instance.PathConnectionLayer[tile] == 0) { + return 0; + } + if ((DAT_TileMapState::instance.MiscDisplayLayer[tile] & 0x1000) != 0) { + return 0; + } + + if ((DAT_TileMapState::instance.LogicLayer[tile] & L_WALL_OR_GATEHOUSE) != 0) { + if (playerID != 0 && (this->WallOwnerLayer[tile] & 7) + 1 != playerID) { + return 0; + } + return DAT_TileMapState::instance.HeightLayer[tile]; + } + + short buildingID = DAT_TileMapState::instance.BuildingLayer[tile]; + if (buildingID == 0) { + return 0; + } + if (playerID != 0 && DAT_BuildingsState::instance.buildings[buildingID].owner != playerID) { + return 0; + } + + switch (DAT_BuildingsState::instance.buildings[buildingID].buildingType) { + 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_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: + for (int direction = 0; direction < 8; direction++) { + if (this->BuildingLayer[DAT_TileMapState::instance.directionTranslationMatrix[DAT_ViewportRenderState:: + instance.tileTranslationMatrix_YComponent[tile]][direction] + + tile] + != buildingID) { + return 0; + } + } + return MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getTotalHeightAtTile, this)(tile); + case OpenSHC::Map::Buildings::BT_GATEHOUSELARGE: + case OpenSHC::Map::Buildings::BT_GATEHOUSESMALL: { + int firstDirection = 0; + if (DAT_BuildingsState::instance.buildings[buildingID].buildingVariation == 0x50) { + firstDirection = 2; + } + int secondDirection = firstDirection + 4; + if (this->BuildingLayer[DAT_TileMapState::instance.directionTranslationMatrix[DAT_ViewportRenderState:: + instance.tileTranslationMatrix_YComponent[tile]][firstDirection] + + tile] + != buildingID) { + return 0; + } + if (this->BuildingLayer[DAT_TileMapState::instance.directionTranslationMatrix[DAT_ViewportRenderState:: + instance.tileTranslationMatrix_YComponent[tile]][secondDirection] + + tile] + != buildingID) { + return 0; + } + return MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getTotalHeightAtTile, this)(tile); + } + } + return 0; + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/getMaxWallHeightInBrushArea.cpp b/src/OpenSHC/Map/TileMapState/getMaxWallHeightInBrushArea.cpp new file mode 100644 index 0000000000..6bb6c92213 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/getMaxWallHeightInBrushArea.cpp @@ -0,0 +1,36 @@ +#include "../TileMapState.func.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_CRENEL; + using OpenSHC::Map::LogicHelpers::L_STOCKPILEUnk; + using OpenSHC::Map::LogicHelpers::L_WALL_OR_GATEHOUSE; + + // FUNCTION: STRONGHOLDCRUSADER 0x00502950 + int TileMapState::getMaxWallHeightInBrushArea(int param_1, uint param_2) + { + int baseTile = param_1; + uint baseY = param_2; + int maxWallHeight = 0; + for (int index = 1; index < 5; index++) { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getTileForBrush, this)( + 1, index, ¶m_1, (int*)¶m_2, baseTile, baseY); + if ((this->LogicLayer[param_1] & L_WALL_OR_GATEHOUSE) == 0) { + continue; + } + if ((this->LogicLayer[param_1] & L_STOCKPILEUnk) != 0) { + continue; + } + if ((this->LogicLayer[param_1] & L_CRENEL) != 0) { + continue; + } + if (this->HeightLayer[param_1] > maxWallHeight) { + maxWallHeight = this->HeightLayer[param_1]; + } + } + return maxWallHeight; + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/getNonFarmFieldBuildingHealthAtTileOr1000.cpp b/src/OpenSHC/Map/TileMapState/getNonFarmFieldBuildingHealthAtTileOr1000.cpp new file mode 100644 index 0000000000..ea298623c1 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/getNonFarmFieldBuildingHealthAtTileOr1000.cpp @@ -0,0 +1,48 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Map/Buildings/BuildingLogicalState.hpp" + +#include "OpenSHC/Globals/DAT_BuildingDefinedData.hpp" +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_FARM_FIELD_APPLE; + using OpenSHC::Map::LogicHelpers::L_FARM_FIELD_DAIRY; + using OpenSHC::Map::LogicHelpers::L_FARM_FIELD_HOP; + using OpenSHC::Map::LogicHelpers::L_FARM_FIELD_WHEAT; + + using OpenSHC::Map::Buildings::BuildingLogicalState; + + // FUNCTION: STRONGHOLDCRUSADER 0x004F8160 + int TileMapState::getNonFarmFieldBuildingHealthAtTileOr1000(int tile) + { + short buildingID = this->BuildingLayer[tile]; + if (buildingID <= 0) { + return 1000; + } + if (DAT_BuildingsState::instance.buildings[buildingID].logicalState == 0) { + return 1000; + } + if (DAT_BuildingsState::instance.buildings[buildingID].logicalState == OpenSHC::Map::Buildings::BLS_REMOVE) { + return 1000; + } + if (DAT_BuildingsState::instance.buildings[buildingID].currentHealth == 0) { + return 1000; + } + if (DAT_BuildingDefinedData::instance + .BuildingTypeHasHealth[DAT_BuildingsState::instance.buildings[buildingID].buildingType] + == 0) { + return 1000; + } + + if ((this->LogicLayer[tile] & (L_FARM_FIELD_WHEAT | L_FARM_FIELD_HOP | L_FARM_FIELD_APPLE | L_FARM_FIELD_DAIRY)) + != 0) { + return 1000; + } + return DAT_BuildingsState::instance.buildings[buildingID].currentHealth; + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/getOrientationThatIsWallTowerOrGatehouse.cpp b/src/OpenSHC/Map/TileMapState/getOrientationThatIsWallTowerOrGatehouse.cpp new file mode 100644 index 0000000000..2d8bff6973 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/getOrientationThatIsWallTowerOrGatehouse.cpp @@ -0,0 +1,38 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Map/MapConstants.hpp" + +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_CRENEL_VARIATIONUnk; + using OpenSHC::Map::LogicHelpers::L_STOCKPILEUnk; + using OpenSHC::Map::LogicHelpers::L_WALL_OR_GATEHOUSE; + + // FUNCTION: STRONGHOLDCRUSADER 0x004F8B50 + int TileMapState::getOrientationThatIsWallTowerOrGatehouse(uint x, uint y) + { + if (x > MC_MAP_XY_LIMIT_INCLUSIVE || y > MC_MAP_XY_LIMIT_INCLUSIVE) { + return 15; + } + if (DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[y * MC_MAP_XY_LIMIT + x] == 0) { + return 15; + } + + int rowTile = DAT_ViewportRenderState::instance.translationMatrix[y].addXgetTile + x; + for (int index = 0; index < 8; index++) { + int orientation = DAT_TerrainDefinedData::instance.SomeOrientationOrderArray[index]; + int neighbour = this->directionTranslationMatrix[y][orientation] + rowTile; + if ((this->LogicLayer[neighbour] & L_WALL_OR_GATEHOUSE) != 0 + && (this->LogicLayer[neighbour] & (L_STOCKPILEUnk | L_CRENEL_VARIATIONUnk)) == 0) { + return orientation; + } + } + return 15; + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/getPitchDitchIDForTile.cpp b/src/OpenSHC/Map/TileMapState/getPitchDitchIDForTile.cpp new file mode 100644 index 0000000000..e2966b9158 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/getPitchDitchIDForTile.cpp @@ -0,0 +1,18 @@ +#include "../TileMapState.func.hpp" + +namespace OpenSHC { +namespace Map { + + // FUNCTION: STRONGHOLDCRUSADER 0x00500850 + int TileMapState::getPitchDitchIDForTile(int tile) + { + for (int pitchDitchID = 1; pitchDitchID < this->maxPitchDitchCount; pitchDitchID++) { + if (this->pitchDitches[pitchDitchID].owner != 0 && tile == this->pitchDitches[pitchDitchID].tile) { + return pitchDitchID; + } + } + return 0; + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/getRubbleGraphicStageForDamageLevel.cpp b/src/OpenSHC/Map/TileMapState/getRubbleGraphicStageForDamageLevel.cpp new file mode 100644 index 0000000000..190058e1d2 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/getRubbleGraphicStageForDamageLevel.cpp @@ -0,0 +1,73 @@ +#include "../TileMapState.func.hpp" + +namespace OpenSHC { +namespace Map { + + // FUNCTION: STRONGHOLDCRUSADER 0x004FA460 + undefined4 TileMapState::getRubbleGraphicStageForDamageLevel(int rotation) + { + /* the result lives in eax from the start (xor eax, eax), every comparison goes through ecx */ + int result = 0; + int orientation = this->mapOrientation; + if (orientation == 0) { + if (rotation == 0x50) { + result = 1; + } else if (rotation == 0x51) { + result = 0; + } else if (rotation == 1) { + result = 2; + } else if (rotation == 7) { + result = 5; + } else if (rotation == 3) { + result = 3; + } else if (rotation == 5) { + result = 4; + } + } else if (orientation == 4) { + if (rotation == 0x50) { + result = 1; + } else if (rotation == 0x51) { + result = 0; + } else if (rotation == 1) { + result = 4; + } else if (rotation == 7) { + result = 3; + } else if (rotation == 3) { + result = 5; + } else if (rotation == 5) { + result = 2; + } + } else if (orientation == 2) { + if (rotation == 0x50) { + result = 0; + } else if (rotation == 0x51) { + result = 1; + } else if (rotation == 1) { + result = 5; + } else if (rotation == 7) { + result = 4; + } else if (rotation == 3) { + result = 2; + } else if (rotation == 5) { + result = 3; + } + } else if (orientation == 6) { + if (rotation == 0x50) { + result = 0; + } else if (rotation == 0x51) { + result = 1; + } else if (rotation == 1) { + result = 3; + } else if (rotation == 7) { + result = 2; + } else if (rotation == 3) { + result = 4; + } else if (rotation == 5) { + result = 5; + } + } + return result; + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/getTileForBrush.cpp b/src/OpenSHC/Map/TileMapState/getTileForBrush.cpp new file mode 100644 index 0000000000..3ada3d1f02 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/getTileForBrush.cpp @@ -0,0 +1,61 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" + +#include "OpenSHC/Globals/DAT_PathFindingState.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + + // FUNCTION: STRONGHOLDCRUSADER 0x004FBD80 + void TileMapState::getTileForBrush(int square, int index, int* tilePointer, int* yPointer, int baseTile, uint y) + { + if (square != 0) { + MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::PathFindingState_Func::getTileInSquareBrush, DAT_PathFindingState::ptr)( + index, baseTile - DAT_ViewportRenderState::instance.translationMatrix[y].addXgetTile, y); + *tilePointer = DAT_PathFindingState::instance.resultTile; + *yPointer = DAT_PathFindingState::instance.resultY; + return; + } + + if (index >= 37) { + index = 0; + } + int brushStep = DAT_TerrainDefinedData::instance.field12_0xc[index]; + if (brushStep == 0xf) { + return; + } + if (brushStep < 8) { + *tilePointer = *tilePointer + this->directionTranslationMatrix[*yPointer][brushStep]; + *yPointer = *yPointer + + DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[brushStep].int_.yOffset; + return; + } + + if (brushStep < 28) { + brushStep = brushStep - 20; + *tilePointer = *tilePointer + this->directionTranslationMatrix[*yPointer][brushStep]; + *yPointer + = *yPointer + DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[brushStep].int_.yOffset; + *tilePointer = *tilePointer + this->directionTranslationMatrix[*yPointer][brushStep]; + *yPointer + = *yPointer + DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[brushStep].int_.yOffset; + } else if (brushStep < 48) { + brushStep = brushStep - 40; + *tilePointer = *tilePointer + this->directionTranslationMatrix[*yPointer][brushStep]; + *yPointer + = *yPointer + DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[brushStep].int_.yOffset; + *tilePointer = *tilePointer + this->directionTranslationMatrix[*yPointer][brushStep]; + *yPointer + = *yPointer + DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[brushStep].int_.yOffset; + *tilePointer = *tilePointer + this->directionTranslationMatrix[*yPointer][brushStep]; + *yPointer + = *yPointer + DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[brushStep].int_.yOffset; + } + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/getTotalHeightAt.cpp b/src/OpenSHC/Map/TileMapState/getTotalHeightAt.cpp new file mode 100644 index 0000000000..9899772550 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/getTotalHeightAt.cpp @@ -0,0 +1,165 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Map/Buildings/BuildingsState.func.hpp" +#include "OpenSHC/Map/Buildings/BuildingType.hpp" + +#include "OpenSHC/Globals/DAT_BuildingDefinedData.hpp" +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_LandscapeState.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_BUILDING; + using OpenSHC::Map::LogicHelpers::L_CRENEL; + using OpenSHC::Map::LogicHelpers::L_CRENEL_VARIATIONUnk; + using OpenSHC::Map::LogicHelpers::L_KEEP_NON_MANOR_HOUSE; + using OpenSHC::Map::LogicHelpers::L_ROCKY; + using OpenSHC::Map::LogicHelpers::L_WALL_OR_GATEHOUSE; + + using OpenSHC::Map::Buildings::BuildingType; + + // FUNCTION: STRONGHOLDCRUSADER 0x004FFBA0 + int TileMapState::getTotalHeightAt(int tile, int playerID) + { + uint logic = this->LogicLayer[tile]; + int extra = 0; + int exposed = 0; + if ((logic & L_KEEP_NON_MANOR_HOUSE) != 0) { + int buildingID = this->BuildingLayer[tile]; + extra = MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::getBuildingHeightForBuildingID, + DAT_BuildingsState::ptr)(buildingID); + for (int i = 0; i < 8; i++) { + if (this->BuildingLayer[DAT_TileMapState::instance.directionTranslationMatrix[DAT_ViewportRenderState:: + instance.tileTranslationMatrix_YComponent[tile]][i] + + tile] + != buildingID) { + exposed = 1; + break; + } + } + if (playerID != 0 && DAT_BuildingsState::instance.buildings[buildingID].owner != playerID) { + exposed = 0; + } + } else if ((logic & L_BUILDING) != 0) { + int buildingID = this->BuildingLayer[tile]; + int type = DAT_BuildingsState::instance.buildings[buildingID].buildingType; + switch (type) { + case 0x3d: + case 0x4a: + case 0x4b: + case 0x4c: + case 0x4d: + case 0x4e: + extra = MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::getBuildingHeightForBuildingID, + DAT_BuildingsState::ptr)(buildingID) + + 0x14; + exposed = 1; + break; + case 0x28: + case 0x29: + case 0x2a: + case 0x2b: + case 0x2c: + extra = MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::getBuildingHeightForBuildingID, + DAT_BuildingsState::ptr)(buildingID); + if (DAT_BuildingsState::instance.buildings[buildingID].buildingType + != OpenSHC::Map::Buildings::BT_MANORHOUSE) { + for (int i = 0; i < 8; i++) { + if (this->BuildingLayer[DAT_TileMapState::instance + .directionTranslationMatrix[DAT_ViewportRenderState::instance + .tileTranslationMatrix_YComponent[tile]][i] + + tile] + != buildingID) { + exposed = 1; + break; + } + } + } + break; + case 0x2d: + case 0x2e: + extra = MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::getBuildingHeightForBuildingID, + DAT_BuildingsState::ptr)(buildingID); + exposed = 1; + break; + default: + extra = DAT_BuildingDefinedData::instance.BuildingHeights[type]; + break; + } + if (playerID != 0 && DAT_BuildingsState::instance.buildings[buildingID].owner != playerID) { + exposed = 0; + } + } else if ((logic & L_ROCKY) != 0 && (logic & L_WALL_OR_GATEHOUSE) == 0) { + /* rock ids are biased by 2000 */ + int organism = this->OrganismLayer[tile]; + if (organism >= 2000) { + short rockType = DAT_LandscapeState::instance.rocks[organism - 2000].type; + if (rockType >= 0xd) { + extra = 0x46; + } else if (rockType >= 9) { + extra = 0x32; + } + } + } else if ((logic & L_CRENEL_VARIATIONUnk) != 0) { + extra = 0x14; + exposed = 1; + if (playerID != 0 && (this->WallOwnerLayer[tile] & 7) + 1 != playerID) { + exposed = 0; + } + } else if ((logic & L_CRENEL) != 0) { + extra = 10; + exposed = 1; + if (playerID != 0 && (this->WallOwnerLayer[tile] & 7) + 1 != playerID) { + exposed = 0; + } + } else { + short building = this->BuildingLayer[tile]; + if (building != 0) { + int buildingID = building; + short type = DAT_BuildingsState::instance.buildings[buildingID].buildingType; + extra = 0x1e; + if (type == OpenSHC::Map::Buildings::BT_GATEHOUSELARGE + || type == OpenSHC::Map::Buildings::BT_GATEHOUSESMALL) { + /* a gatehouse only counts as cover while both of its span tiles are still standing */ + int first; + int second; + if (DAT_BuildingsState::instance.buildings[buildingID].buildingVariation == 0x50) { + first = 2; + second = 6; + } else { + first = 0; + second = 4; + } + if (this->BuildingLayer[DAT_TileMapState::instance + .directionTranslationMatrix[DAT_ViewportRenderState::instance + .tileTranslationMatrix_YComponent[tile]][first] + + tile] + != buildingID) { + exposed = 1; + } + if (this->BuildingLayer[DAT_TileMapState::instance + .directionTranslationMatrix[DAT_ViewportRenderState::instance + .tileTranslationMatrix_YComponent[tile]][second] + + tile] + != buildingID) { + exposed = 1; + } + } + if (playerID != 0 && DAT_BuildingsState::instance.buildings[buildingID].owner != playerID) { + exposed = 0; + } + } + } + + extra = extra + this->HeightLayer[tile]; + if (exposed != 0) { + return extra; + } + return -1 - extra; + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/getTotalHeightAtTile.cpp b/src/OpenSHC/Map/TileMapState/getTotalHeightAtTile.cpp new file mode 100644 index 0000000000..844faef35d --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/getTotalHeightAtTile.cpp @@ -0,0 +1,38 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Map/Buildings/BuildingsState.func.hpp" +#include "OpenSHC/Map/Buildings/BuildingType.hpp" + +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::Buildings::BuildingType; + + // FUNCTION: STRONGHOLDCRUSADER 0x004FFB10 + uint TileMapState::getTotalHeightAtTile(int tile) + { + int buildingID = this->BuildingLayer[tile]; + if (buildingID != 0) { + if (DAT_BuildingsState::instance.buildings[buildingID].buildingType + == OpenSHC::Map::Buildings::BT_GATEHOUSELARGE) { + return MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::getBuildingHeightForBuildingID, + DAT_BuildingsState::ptr)(buildingID) + + this->DefaultHeightLayer[tile]; + } + if (DAT_BuildingsState::instance.buildings[buildingID].buildingType + == OpenSHC::Map::Buildings::BT_GATEHOUSESMALL) { + return MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::getBuildingHeightForBuildingID, + DAT_BuildingsState::ptr)(buildingID) + + this->DefaultHeightLayer[tile]; + } + return MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::getBuildingHeightForBuildingID, + DAT_BuildingsState::ptr)(buildingID) + + this->HeightLayer[tile]; + } + return this->HeightLayer[tile]; + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/getWallFlagForOrientedDirection.cpp b/src/OpenSHC/Map/TileMapState/getWallFlagForOrientedDirection.cpp new file mode 100644 index 0000000000..5cb13a1013 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/getWallFlagForOrientedDirection.cpp @@ -0,0 +1,37 @@ +#include "../TileMapState.func.hpp" + +namespace OpenSHC { +namespace Map { + + // FUNCTION: STRONGHOLDCRUSADER 0x004F89C0 + uint TileMapState::getWallFlagForOrientedDirection(int tileUnk, int y, int twoOrFour) + { + int direction = 0; + if (twoOrFour == 2) { + if (this->mapOrientation == 0) { + direction = 2; + } else if (this->mapOrientation == 2) { + direction = 4; + } else if (this->mapOrientation == 4) { + direction = 6; + } else if (this->mapOrientation == 6) { + direction = 0; + } + } else if (twoOrFour == 4) { + if (this->mapOrientation == 0) { + direction = 4; + } else if (this->mapOrientation == 2) { + direction = 6; + } else if (this->mapOrientation == 4) { + direction = 0; + } else if (this->mapOrientation == 6) { + direction = 2; + } + } else { + return 0; + } + return (uint)this->LogicLayer[this->directionTranslationMatrix[y][direction] + tileUnk] >> 8 & 1; + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/hasHigherNeighborWithStairs.cpp b/src/OpenSHC/Map/TileMapState/hasHigherNeighborWithStairs.cpp new file mode 100644 index 0000000000..9c6392c669 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/hasHigherNeighborWithStairs.cpp @@ -0,0 +1,35 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x004F8A40 + BOOLEnum TileMapState::hasHigherNeighborWithStairs(int tileUnk, int y, int direction) + { + int rotatedDirection = 0; + if (this->mapOrientation == 0) { + rotatedDirection = direction; + } else if (this->mapOrientation == 4) { + rotatedDirection = direction + 4; + } else if (this->mapOrientation == 2) { + rotatedDirection = direction + 2; + } else if (this->mapOrientation == 6) { + rotatedDirection = direction + 6; + } + if (rotatedDirection >= 8) { + rotatedDirection = rotatedDirection - 8; + } + + int neighbour = this->directionTranslationMatrix[y][rotatedDirection] + tileUnk; + if (this->HeightLayer[neighbour] <= this->HeightLayer[tileUnk]) { + return FALSE; + } + return (uint)this->LogicLayer[neighbour] >> 0xb & TRUE; + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/hasHigherPlainNeighborWithWallOrGatehouse.cpp b/src/OpenSHC/Map/TileMapState/hasHigherPlainNeighborWithWallOrGatehouse.cpp new file mode 100644 index 0000000000..39ebc54d76 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/hasHigherPlainNeighborWithWallOrGatehouse.cpp @@ -0,0 +1,44 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_CRENEL; + using OpenSHC::Map::LogicHelpers::L_STOCKPILEUnk; + + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x004F8AC0 + BOOLEnum TileMapState::hasHigherPlainNeighborWithWallOrGatehouse(int tile, int y, int direction) + { + int rotatedDirection = 0; + if (this->mapOrientation == 0) { + rotatedDirection = direction; + } else if (this->mapOrientation == 4) { + rotatedDirection = direction + 4; + } else if (this->mapOrientation == 2) { + rotatedDirection = direction + 2; + } else if (this->mapOrientation == 6) { + rotatedDirection = direction + 6; + } + if (rotatedDirection >= 8) { + rotatedDirection = rotatedDirection - 8; + } + + int neighbour = this->directionTranslationMatrix[y][rotatedDirection] + tile; + if (this->HeightLayer[tile] >= this->HeightLayer[neighbour]) { + return FALSE; + } + if ((this->LogicLayer[neighbour] & L_CRENEL) != 0) { + return FALSE; + } + if ((this->LogicLayer[neighbour] & L_STOCKPILEUnk) != 0) { + return FALSE; + } + return this->LogicLayer[neighbour] >> 8 & TRUE; + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/hasOnlyTowerNeighborsNoWalls.cpp b/src/OpenSHC/Map/TileMapState/hasOnlyTowerNeighborsNoWalls.cpp new file mode 100644 index 0000000000..fdaf81b454 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/hasOnlyTowerNeighborsNoWalls.cpp @@ -0,0 +1,49 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_UNKNOWN_WALL_RELATED; + using OpenSHC::Map::LogicHelpers::L_WALL_OR_GATEHOUSE; + + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x004F8900 + BOOLEnum TileMapState::hasOnlyTowerNeighborsNoWalls(int tile, int y) + { + int unknownWallRelated = 0; + int wallOrGatehouse = 0; + int offset = this->directionTranslationMatrix[y][0] + tile; + if ((this->LogicLayer[offset] & L_UNKNOWN_WALL_RELATED) != 0) { + unknownWallRelated++; + } else if ((this->LogicLayer[offset] & L_WALL_OR_GATEHOUSE) != 0) { + wallOrGatehouse++; + } + offset = this->directionTranslationMatrix[y][2] + tile; + if ((this->LogicLayer[offset] & L_UNKNOWN_WALL_RELATED) != 0) { + unknownWallRelated++; + } else if ((this->LogicLayer[offset] & L_WALL_OR_GATEHOUSE) != 0) { + wallOrGatehouse++; + } + offset = this->directionTranslationMatrix[y][4] + tile; + if ((this->LogicLayer[offset] & L_UNKNOWN_WALL_RELATED) != 0) { + unknownWallRelated++; + } else if ((this->LogicLayer[offset] & L_WALL_OR_GATEHOUSE) != 0) { + wallOrGatehouse++; + } + offset = this->directionTranslationMatrix[y][6] + tile; + if ((this->LogicLayer[offset] & L_UNKNOWN_WALL_RELATED) != 0) { + unknownWallRelated++; + } else if ((this->LogicLayer[offset] & L_WALL_OR_GATEHOUSE) != 0) { + wallOrGatehouse++; + } + if (unknownWallRelated != 0 && wallOrGatehouse == 0) { + return TRUE; + } + return FALSE; + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/increaseHeightForTunnelSingleTile.cpp b/src/OpenSHC/Map/TileMapState/increaseHeightForTunnelSingleTile.cpp new file mode 100644 index 0000000000..94a8ee8f8d --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/increaseHeightForTunnelSingleTile.cpp @@ -0,0 +1,48 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" + +#include "OpenSHC/Globals/DAT_PathFindingState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_BORDER; + using OpenSHC::Map::LogicHelpers::L_BORDER_EDGE; + using OpenSHC::Map::LogicHelpers::L_BUILDING; + using OpenSHC::Map::LogicHelpers::L_FORD; + using OpenSHC::Map::LogicHelpers::L_KEEP_NON_MANOR_HOUSE; + using OpenSHC::Map::LogicHelpers::L_MARSH; + using OpenSHC::Map::LogicHelpers::L_MOAT; + using OpenSHC::Map::LogicHelpers::L_RIVER; + using OpenSHC::Map::LogicHelpers::L_ROCKY; + using OpenSHC::Map::LogicHelpers::L_SEA; + using OpenSHC::Map::LogicHelpers::L_WALL_OR_GATEHOUSE; + + // FUNCTION: STRONGHOLDCRUSADER 0x004F80E0 + void TileMapState::increaseHeightForTunnelSingleTile(int tile, uint x, uint y, int increment) + { + if ((this->LogicLayer[tile] + & (L_WALL_OR_GATEHOUSE | L_BUILDING | L_RIVER | L_FORD | L_KEEP_NON_MANOR_HOUSE | L_MARSH | L_MOAT)) + != 0) { + return; + } + if ((this->LogicLayer[tile] & (L_SEA | L_BORDER | L_BORDER_EDGE | L_ROCKY)) != 0) { + return; + } + if (this->BuildingLayer[tile] != 0) { + return; + } + + if ((this->HeightLayer[tile] < 16 || this->DefaultHeightLayer[tile] < 16) + && (int)((uint)this->HeightLayer[tile] + increment) >= 0) { + this->HeightLayer[tile] = this->HeightLayer[tile] + (char)increment; + } + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::updateWalkAndPathLayer, + DAT_PathFindingState::ptr)(4, x, y); + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::updatePathLinkagesInAllEightDirections, + DAT_PathFindingState::ptr)(y, tile); + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/increaseHeightForTunnelWithBrush.cpp b/src/OpenSHC/Map/TileMapState/increaseHeightForTunnelWithBrush.cpp new file mode 100644 index 0000000000..66ec06990d --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/increaseHeightForTunnelWithBrush.cpp @@ -0,0 +1,55 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" + +#include "OpenSHC/Globals/DAT_PathFindingState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_BORDER; + using OpenSHC::Map::LogicHelpers::L_BORDER_EDGE; + using OpenSHC::Map::LogicHelpers::L_BUILDING; + using OpenSHC::Map::LogicHelpers::L_FORD; + using OpenSHC::Map::LogicHelpers::L_KEEP_NON_MANOR_HOUSE; + using OpenSHC::Map::LogicHelpers::L_MARSH; + using OpenSHC::Map::LogicHelpers::L_MOAT; + using OpenSHC::Map::LogicHelpers::L_RIVER; + using OpenSHC::Map::LogicHelpers::L_ROCKY; + using OpenSHC::Map::LogicHelpers::L_SEA; + using OpenSHC::Map::LogicHelpers::L_WALL_OR_GATEHOUSE; + + // FUNCTION: STRONGHOLDCRUSADER 0x00501CD0 + void TileMapState::increaseHeightForTunnelWithBrush(int tile, uint x, uint y, int increment) + { + int baseTile = tile; + uint baseY = y; + for (int index = 0; index < 9; index++) { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getTileForBrush, this)( + 0, index, &tile, (int*)&y, baseTile, baseY); + if ((this->LogicLayer[tile] & (L_WALL_OR_GATEHOUSE | L_BUILDING | L_KEEP_NON_MANOR_HOUSE)) != 0) { + continue; + } + if (this->BuildingLayer[tile] != 0) { + continue; + } + if ((this->LogicLayer[tile] & (L_SEA | L_BORDER | L_BORDER_EDGE | L_ROCKY)) != 0) { + continue; + } + if ((this->LogicLayer[tile] & (L_RIVER | L_FORD | L_MARSH | L_MOAT)) != 0) { + continue; + } + + if ((this->HeightLayer[tile] < 0x10 || this->DefaultHeightLayer[tile] < 0x10) + && (int)((uint)this->HeightLayer[tile] + increment) >= 0) { + this->HeightLayer[tile] = this->HeightLayer[tile] + (char)increment; + } + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::updatePathLinkagesInAllEightDirections, + DAT_PathFindingState::ptr)(y, tile); + } + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::updateWalkAndPathLayer, + DAT_PathFindingState::ptr)(5, x, y); + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/isBuildingPlacementAllowedAtTile.cpp b/src/OpenSHC/Map/TileMapState/isBuildingPlacementAllowedAtTile.cpp new file mode 100644 index 0000000000..f24d4a16eb --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/isBuildingPlacementAllowedAtTile.cpp @@ -0,0 +1,222 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Synchrony/GameSynchronyState.func.hpp" +#include "OpenSHC/Commands/MappersEnum.hpp" +#include "OpenSHC/Game/GameMode.hpp" +#include "OpenSHC/Map/Units/UnitType.hpp" +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +#include "OpenSHC/Globals/DAT_GameSynchronyState.hpp" +#include "OpenSHC/Globals/DAT_LandscapeState.hpp" +#include "OpenSHC/Globals/DAT_UnitsState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_BORDER; + using OpenSHC::Map::LogicHelpers::L_BORDER_EDGE; + using OpenSHC::Map::LogicHelpers::L_BUILDING; + using OpenSHC::Map::LogicHelpers::L_FARM_FIELD_APPLE; + using OpenSHC::Map::LogicHelpers::L_FARM_FIELD_DAIRY; + using OpenSHC::Map::LogicHelpers::L_FARM_FIELD_HOP; + using OpenSHC::Map::LogicHelpers::L_FARM_FIELD_WHEAT; + using OpenSHC::Map::LogicHelpers::L_FORD; + using OpenSHC::Map::LogicHelpers::L_KEEP_NON_MANOR_HOUSE; + using OpenSHC::Map::LogicHelpers::L_MARSH; + using OpenSHC::Map::LogicHelpers::L_MOAT; + using OpenSHC::Map::LogicHelpers::L_PLAIN1_AND_FARM; + using OpenSHC::Map::LogicHelpers::L_PLAIN2_AND_PITCH; + using OpenSHC::Map::LogicHelpers::L_RIVER; + using OpenSHC::Map::LogicHelpers::L_SEA; + using OpenSHC::Map::LogicHelpers::L_TREE; + using OpenSHC::Map::LogicHelpers::L_TREE_VARIATION; + using OpenSHC::Map::LogicHelpers::L_WALL_OR_GATEHOUSE; + + using OpenSHC::Commands::MappersEnum; + using OpenSHC::Game::GameMode; + using OpenSHC::Map::Units::UnitType; + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x004F9A60 + int TileMapState::isBuildingPlacementAllowedAtTile( + int tile, int playerID, MappersEnum commandBuildingType, int param_4) + { + uint logic = this->LogicLayer[tile]; + uint wallOrGate = logic & L_WALL_OR_GATEHOUSE; + uint height = this->HeightLayer[tile]; + if (wallOrGate != 0 && (this->WallOwnerLayer[tile] & 7) + 1 == playerID) { + /* a gate or tower on our own wall is measured against the ground, not the wall top */ + switch (commandBuildingType) { + case OpenSHC::Commands::M_MAPPER_GATEHOUSE: + case OpenSHC::Commands::M_MAPPER_GATE_MAIN: + case OpenSHC::Commands::M_MAPPER_GATE_INNER: + case OpenSHC::Commands::M_MAPPER_GATE_WOOD: + case OpenSHC::Commands::M_MAPPER_GATE_POSTERN: + case OpenSHC::Commands::M_MAPPER_TOWER1: + case OpenSHC::Commands::M_MAPPER_TOWER2: + case OpenSHC::Commands::M_MAPPER_TOWER3: + case OpenSHC::Commands::M_MAPPER_TOWER4: + case OpenSHC::Commands::M_MAPPER_TOWER5: + case OpenSHC::Commands::M_MAPPER_GATE_WOOD1A: + case OpenSHC::Commands::M_MAPPER_GATE_WOOD1B: + case OpenSHC::Commands::M_MAPPER_GATE_WOOD1C: + case OpenSHC::Commands::M_MAPPER_GATE_WOOD1D: + case OpenSHC::Commands::M_MAPPER_GATE_STONE1A: + case OpenSHC::Commands::M_MAPPER_GATE_STONE1B: + case OpenSHC::Commands::M_MAPPER_GATE_STONE2A: + case OpenSHC::Commands::M_MAPPER_GATE_STONE2B: + height = this->DefaultHeightLayer[tile]; + } + } + + if (this->buildingHeightLimit < 0) { + if ((int)height < -this->buildingHeightLimit) { + return 1; + } + } else if (this->buildingHeightLimit < (int)height) { + if (commandBuildingType == OpenSHC::Commands::M_MAPPER_CATTLEFARM) { + this->placementWarning = 1; + return 1; + } + if (commandBuildingType == OpenSHC::Commands::M_MAPPER_APPLEFARM) { + this->placementWarning = 2; + return 1; + } + if (commandBuildingType == OpenSHC::Commands::M_MAPPER_HOPSFARM) { + this->placementWarning = 3; + return 1; + } + if (commandBuildingType != OpenSHC::Commands::M_MAPPER_WHEATFARM) { + return 1; + } + this->placementWarning = 4; + return 1; + } + if (this->buildingMaxHeightDifference + this->buildingMinHeight < (int)height) { + return 1; + } + if ((logic & L_PLAIN2_AND_PITCH) != 0 && commandBuildingType == OpenSHC::Commands::M_MAPPER_PITCH_DITCH) { + return 1; + } + if (this->BuildingLayer[tile] != 0) { + return 2; + } + + if (this->UnitLayer[tile] != 0) { + int unitID = (short)this->UnitLayer[tile]; + if (MACRO_CALL_MEMBER(OpenSHC::Synchrony::GameSynchronyState_Func::isAIPlayer, DAT_GameSynchronyState::ptr)( + playerID) + == FALSE) { + if (DAT_UnitsState::instance.units[unitID].unitType != OpenSHC::Map::Units::UT_CHICKEN) { + return 1; + } + } else { + if (DAT_UnitsState::instance.units[unitID].unitType == OpenSHC::Map::Units::UT_LORD) { + return 1; + } + if (DAT_UnitsState::instance.units[unitID].isSelectable_OR_matchTime != 0 + && DAT_UnitsState::instance.units[unitID].owner != playerID) { + return 1; + } + } + } + + if ((logic & L_SEA) != 0) { + return 1; + } + if ((logic & (L_BORDER | L_BORDER_EDGE)) != 0) { + return 1; + } + if ((logic & L_RIVER) != 0) { + return 1; + } + if (wallOrGate != 0) { + if ((this->WallOwnerLayer[tile] & 7) + 1 != playerID) { + return 1; + } + /* only a gate or a tower may be built onto a wall */ + switch (commandBuildingType) { + case OpenSHC::Commands::M_MAPPER_GATEHOUSE: + case OpenSHC::Commands::M_MAPPER_GATE_MAIN: + case OpenSHC::Commands::M_MAPPER_GATE_INNER: + case OpenSHC::Commands::M_MAPPER_GATE_WOOD: + case OpenSHC::Commands::M_MAPPER_GATE_POSTERN: + case OpenSHC::Commands::M_MAPPER_TOWER1: + case OpenSHC::Commands::M_MAPPER_TOWER2: + case OpenSHC::Commands::M_MAPPER_TOWER3: + case OpenSHC::Commands::M_MAPPER_TOWER4: + case OpenSHC::Commands::M_MAPPER_TOWER5: + case OpenSHC::Commands::M_MAPPER_GATE_WOOD1A: + case OpenSHC::Commands::M_MAPPER_GATE_WOOD1B: + case OpenSHC::Commands::M_MAPPER_GATE_WOOD1C: + case OpenSHC::Commands::M_MAPPER_GATE_WOOD1D: + case OpenSHC::Commands::M_MAPPER_GATE_STONE1A: + case OpenSHC::Commands::M_MAPPER_GATE_STONE1B: + case OpenSHC::Commands::M_MAPPER_GATE_STONE2A: + case OpenSHC::Commands::M_MAPPER_GATE_STONE2B: + break; + default: + return 1; + } + } + if ((logic & L_PLAIN1_AND_FARM) != 0 && param_4 == 0) { + return 1; + } + if ((logic & (L_BUILDING | L_KEEP_NON_MANOR_HOUSE)) != 0) { + return 1; + } + + if ((logic & (L_TREE | L_TREE_VARIATION)) != 0 && this->OrganismLayer[tile] != 0 + && this->OrganismLayer[tile] < 2000) { + /* scrub can be built over, a real tree cannot, except by the AI outside solitary */ + switch (DAT_LandscapeState::instance.trees[this->OrganismLayer[tile]].treeType) { + case (TreeType)5: + case (TreeType)6: + case (TreeType)7: + case (TreeType)8: + case (TreeType)9: + case (TreeType)0xa: + case (TreeType)0xb: + case (TreeType)0xc: + case (TreeType)0xd: + case (TreeType)0xe: + case (TreeType)0x10: + case (TreeType)0x11: + case (TreeType)0x12: + case (TreeType)0x13: + break; + default: + if (DAT_GameSynchronyState::instance.currentGameMode == OpenSHC::Game::GM_SOLITARY) { + return 1; + } + if (MACRO_CALL_MEMBER( + OpenSHC::Synchrony::GameSynchronyState_Func::isAIPlayer, DAT_GameSynchronyState::ptr)(playerID) + == 0) { + return 1; + } + } + } + + if ((logic & (L_FARM_FIELD_WHEAT | L_FARM_FIELD_HOP | L_FARM_FIELD_APPLE | L_FARM_FIELD_DAIRY)) != 0 + && param_4 == 0) { + return 1; + } + if ((logic & L_FORD) != 0) { + return 1; + } + + bool onRock = false; + if ((char)logic < 0 && wallOrGate == 0) { + onRock = true; + } + if ((!onRock || this->buildingPlacementProperty_4 != 0) + && ((logic & L_MOAT) == 0 || this->buildingPlacementProperty_7 != 0) + && (this->buildingPlacementProperty_6 == 2 || (logic & L_MARSH) == 0 + || this->buildingPlacementProperty_6 != 0)) { + return 0; + } + return 1; + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/isCliffDropInDirection.cpp b/src/OpenSHC/Map/TileMapState/isCliffDropInDirection.cpp new file mode 100644 index 0000000000..b780f960b1 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/isCliffDropInDirection.cpp @@ -0,0 +1,15 @@ +#include "../TileMapState.func.hpp" + +namespace OpenSHC { +namespace Map { + + // FUNCTION: STRONGHOLDCRUSADER 0x004FC7C0 + BOOLEnum TileMapState::isCliffDropInDirection(int tileUnk, undefined4 param_2, int y) + { + int direction = (this->screenSouthEastDirection + 4) % 8; + return this->HeightLayer[tileUnk] + > this->HeightLayer[this->directionTranslationMatrix[y][direction] + tileUnk] + 0x14; + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/isFootprintIndexOnEdge.cpp b/src/OpenSHC/Map/TileMapState/isFootprintIndexOnEdge.cpp new file mode 100644 index 0000000000..70401976c2 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/isFootprintIndexOnEdge.cpp @@ -0,0 +1,29 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x004F9930 + BOOLEnum TileMapState::isFootprintIndexOnEdge(int counter, int size) + { + if (size < 3) { + return TRUE; + } + if (counter < size) { + return TRUE; + } + if (counter >= (size - 1) * size) { + return TRUE; + } + if (counter % size == 0) { + return TRUE; + } + return counter % size == size - 1; + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/isTileEnclosedByWalls.cpp b/src/OpenSHC/Map/TileMapState/isTileEnclosedByWalls.cpp new file mode 100644 index 0000000000..1ff7b7e5d4 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/isTileEnclosedByWalls.cpp @@ -0,0 +1,32 @@ +#include "../TileMapState.func.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_STOCKPILEUnk; + using OpenSHC::Map::LogicHelpers::L_WALL_OR_GATEHOUSE; + + // FUNCTION: STRONGHOLDCRUSADER 0x004F8640 + undefined4 TileMapState::isTileEnclosedByWalls(int tile, int y) + { + int offset = this->directionTranslationMatrix[y][0] + tile; + if ((this->LogicLayer[offset] & L_WALL_OR_GATEHOUSE) != 0 && (this->LogicLayer[offset] & L_STOCKPILEUnk) == 0) { + return 1; + } + offset = this->directionTranslationMatrix[y][4] + tile; + if ((this->LogicLayer[offset] & L_WALL_OR_GATEHOUSE) != 0 && (this->LogicLayer[offset] & L_STOCKPILEUnk) == 0) { + return 1; + } + offset = this->directionTranslationMatrix[y][2] + tile; + if ((this->LogicLayer[offset] & L_WALL_OR_GATEHOUSE) != 0 && (this->LogicLayer[offset] & L_STOCKPILEUnk) == 0) { + return 1; + } + offset = this->directionTranslationMatrix[y][6] + tile; + if ((this->LogicLayer[offset] & L_WALL_OR_GATEHOUSE) != 0 && (this->LogicLayer[offset] & L_STOCKPILEUnk) == 0) { + return 1; + } + return 0; + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/isTileEnclosedByWallsOrGates.cpp b/src/OpenSHC/Map/TileMapState/isTileEnclosedByWallsOrGates.cpp new file mode 100644 index 0000000000..dfb35c7c91 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/isTileEnclosedByWallsOrGates.cpp @@ -0,0 +1,41 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_CRENEL; + using OpenSHC::Map::LogicHelpers::L_STOCKPILEUnk; + using OpenSHC::Map::LogicHelpers::L_WALL_OR_GATEHOUSE; + + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x004F85B0 + BOOLEnum TileMapState::isTileEnclosedByWallsOrGates(int tile, int y) + { + int offset = this->directionTranslationMatrix[y][0] + tile; + if ((this->LogicLayer[offset] & L_WALL_OR_GATEHOUSE) != 0 + && (this->LogicLayer[offset] & (L_STOCKPILEUnk | L_CRENEL)) == 0) { + return TRUE; + } + offset = this->directionTranslationMatrix[y][4] + tile; + if ((this->LogicLayer[offset] & L_WALL_OR_GATEHOUSE) != 0 + && (this->LogicLayer[offset] & (L_STOCKPILEUnk | L_CRENEL)) == 0) { + return TRUE; + } + offset = this->directionTranslationMatrix[y][2] + tile; + if ((this->LogicLayer[offset] & L_WALL_OR_GATEHOUSE) != 0 + && (this->LogicLayer[offset] & (L_STOCKPILEUnk | L_CRENEL)) == 0) { + return TRUE; + } + offset = this->directionTranslationMatrix[y][6] + tile; + if ((this->LogicLayer[offset] & L_WALL_OR_GATEHOUSE) != 0 + && (this->LogicLayer[offset] & (L_STOCKPILEUnk | L_CRENEL)) == 0) { + return TRUE; + } + return FALSE; + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/isTileSuitableForBrushPlacement.cpp b/src/OpenSHC/Map/TileMapState/isTileSuitableForBrushPlacement.cpp new file mode 100644 index 0000000000..b8197c358c --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/isTileSuitableForBrushPlacement.cpp @@ -0,0 +1,86 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Rendering/ViewportRenderState.func.hpp" +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x004FBE70 + BOOLEnum TileMapState::isTileSuitableForBrushPlacement(int tile, uint x, uint y) + { + byte height = this->HeightLayer[tile]; + /* the tile suits a brush as soon as it stands above any one of its eight neighbours */ + uint neighbourY = y - 1; + if (x <= 399 && neighbourY <= 399 + && DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[neighbourY * 400 + x] != 0 + && (int)(height + - this->HeightLayer[DAT_ViewportRenderState::instance.translationMatrix[y - 1].addXgetTile + x]) + > 0) { + return TRUE; + } + uint neighbourX = x + 1; + if (neighbourX <= 399 && neighbourY <= 399 + && DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[neighbourY * 400 + neighbourX] != 0 + && (int)(height + - this->HeightLayer[DAT_ViewportRenderState::instance.translationMatrix[y - 1].addXgetTile + x + 1]) + > 0) { + return TRUE; + } + if (neighbourX <= 399 && y <= 399 + && DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[y * 400 + neighbourX] != 0 + && (int)(height + - this->HeightLayer[DAT_ViewportRenderState::instance.translationMatrix[y].addXgetTile + x + 1]) + > 0) { + return TRUE; + } + neighbourY = y + 1; + if (neighbourX <= 399 && neighbourY <= 399 + && DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[neighbourY * 400 + neighbourX] != 0 + && (int)(height + - this->HeightLayer[DAT_ViewportRenderState::instance.translationMatrix[y + 1].addXgetTile + x + 1]) + > 0) { + return TRUE; + } + if (x <= 399 && neighbourY <= 399 + && DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[neighbourY * 400 + x] != 0 + && (int)(height + - this->HeightLayer[DAT_ViewportRenderState::instance.translationMatrix[y + 1].addXgetTile + x]) + > 0) { + return TRUE; + } + neighbourX = x - 1; + if (neighbourX <= 399 && neighbourY <= 399 + && DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[neighbourY * 400 + neighbourX] != 0 + && (int)(height + - this->HeightLayer[DAT_ViewportRenderState::instance.translationMatrix[y + 1].addXgetTile + x - 1]) + > 0) { + return TRUE; + } + if (neighbourX <= 399 && y <= 399 + && DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[y * 400 + neighbourX] != 0 + && (int)(height + - this->HeightLayer[DAT_ViewportRenderState::instance.translationMatrix[y].addXgetTile + x - 1]) + > 0) { + return TRUE; + } + + if (MACRO_CALL_MEMBER(OpenSHC::Rendering::ViewportRenderState_Func::xyAreValid, DAT_ViewportRenderState::ptr)( + neighbourX, y - 1) + == FALSE) { + return FALSE; + } + if ((int)(height + - this->HeightLayer[DAT_ViewportRenderState::instance.translationMatrix[y - 1].addXgetTile + x - 1]) + < 1) { + return FALSE; + } + return TRUE; + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/isUnitBlockingSizeFiveFootprint.cpp b/src/OpenSHC/Map/TileMapState/isUnitBlockingSizeFiveFootprint.cpp new file mode 100644 index 0000000000..0c8f5fc477 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/isUnitBlockingSizeFiveFootprint.cpp @@ -0,0 +1,37 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x004FAEE0 + BOOLEnum TileMapState::isUnitBlockingSizeFiveFootprint(int buildingID) + { + int buildingX = DAT_BuildingsState::instance.buildings[buildingID].x; + int buildingY = DAT_BuildingsState::instance.buildings[buildingID].y; + int variation = DAT_BuildingsState::instance.buildings[buildingID].buildingVariation / 2; + int buildingSizeTileIndex = 0; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)( + buildingSizeTileIndex, 5); + if (DAT_TerrainDefinedData::instance.field2338_0x21ec[variation][buildingSizeTileIndex] == 0 + && this->UnitLayer[DAT_ViewportRenderState::instance.translationMatrix[this->buildingY + buildingY] + .addXgetTile + + this->buildingX + buildingX] + != 0) { + return TRUE; + } + buildingSizeTileIndex++; + } while (buildingSizeTileIndex < this->constructionTileCount); + return FALSE; + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/isValidCastleSiteLocation.cpp b/src/OpenSHC/Map/TileMapState/isValidCastleSiteLocation.cpp new file mode 100644 index 0000000000..23a82fcb14 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/isValidCastleSiteLocation.cpp @@ -0,0 +1,109 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" +#include "OpenSHC/Game/GameMode.hpp" +#include "OpenSHC/Game/GameMode2.hpp" +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +#include "OpenSHC/Globals/DAT_GameCore.hpp" +#include "OpenSHC/Globals/DAT_GameSynchronyState.hpp" +#include "OpenSHC/Globals/DAT_PathFindingState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_BOULDERS; + using OpenSHC::Map::LogicHelpers::L_BUILDING; + using OpenSHC::Map::LogicHelpers::L_FORD; + using OpenSHC::Map::LogicHelpers::L_IRON; + using OpenSHC::Map::LogicHelpers::L_KEEP_NON_MANOR_HOUSE; + using OpenSHC::Map::LogicHelpers::L_MARSH; + using OpenSHC::Map::LogicHelpers::L_MOAT; + using OpenSHC::Map::LogicHelpers::L_MOAT_DUG_OR_PLANNED; + using OpenSHC::Map::LogicHelpers::L_PLAIN1_AND_FARM; + using OpenSHC::Map::LogicHelpers::L_RIVER; + using OpenSHC::Map::LogicHelpers::L_ROCKY; + using OpenSHC::Map::LogicHelpers::L_SEA; + using OpenSHC::Map::LogicHelpers::L_WALL_OR_GATEHOUSE; + + using OpenSHC::Game::GameMode; + using OpenSHC::Game::GameMode2; + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x005024F0 + BOOLEnum TileMapState::isValidCastleSiteLocation(int x, uint y, int cbt) + { + int baseTile = DAT_ViewportRenderState::instance.translationMatrix[y].addXgetTile + x; + uint baseY = y; + /* x is reused as the count of tiles that qualified */ + x = 0; + + int enemyRange; + int searchRange; + if (DAT_GameSynchronyState::instance.currentGameMode != OpenSHC::Game::GM_SOLITARY) { + enemyRange = 15; + searchRange = 7; + } else { + enemyRange = 30; + searchRange = 30; + } + + int tile = baseTile; + for (int index = 0; index < 9; index++) { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getTileForBrush, this)( + 0, index, &tile, (int*)&y, baseTile, baseY); + /* the brush call may move both, so the original keeps its own copies for later use */ + int brushTile = tile; + uint brushY = y; + if (this->OrganismLayer[tile] != 0) { + continue; + } + if ((this->LogicLayer[tile] & (L_BUILDING | L_KEEP_NON_MANOR_HOUSE)) != 0) { + continue; + } + if (this->BuildingLayer[tile] != 0) { + continue; + } + if ((this->LogicLayer[tile] & (L_WALL_OR_GATEHOUSE | L_BOULDERS | L_IRON | L_RIVER | L_FORD | L_MARSH)) + != 0) { + continue; + } + if ((this->LogicLayer[tile] & (L_SEA | L_PLAIN1_AND_FARM | L_ROCKY)) != 0) { + continue; + } + + uint brushX = tile - DAT_ViewportRenderState::instance.translationMatrix[y].addXgetTile; + if (DAT_GameCore::instance.gameMode_2 != OpenSHC::Game::GM_EDITOR + && DAT_GameCore::instance.gameMode_2 != OpenSHC::Game::GM_SIEGE_THAT + && MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::PathFindingState_Func::isEnemyTooCloseUnk, DAT_PathFindingState::ptr)( + DAT_GameSynchronyState::instance.currentPlayerSlotID, brushX, y, enemyRange) + != FALSE) { + continue; + } + if (DAT_GameSynchronyState::instance.currentGameMode != OpenSHC::Game::GM_SOLITARY) { + int buildRange + = MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getCastleBuildRangeForMapSize, this)(); + if (MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::isOpponentBuildingInRange, + DAT_PathFindingState::ptr)(DAT_GameSynchronyState::instance.currentPlayerSlotID, brushX, brushY, + searchRange, -1, -1, buildRange + 5) + != 0) { + continue; + } + } + + /* a moat site must be clear of moat, a moat-fill site must sit on one */ + if (cbt == 0x6a) { + if ((this->LogicLayer[brushTile] & (L_MOAT | L_MOAT_DUG_OR_PLANNED)) == 0) { + x = x + 1; + } + } else if (cbt != 0x6b || (this->LogicLayer[brushTile] & L_MOAT_DUG_OR_PLANNED) != 0) { + x = x + 1; + } + } + return (BOOLEnum)(x != 0); + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/isWallConnectionHeightValid.cpp b/src/OpenSHC/Map/TileMapState/isWallConnectionHeightValid.cpp new file mode 100644 index 0000000000..2e4365e8e8 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/isWallConnectionHeightValid.cpp @@ -0,0 +1,60 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_STOCKPILEUnk; + using OpenSHC::Map::LogicHelpers::L_WALL_OR_GATEHOUSE; + + using OpenSHC::Map::LogicHelpers::L_STOCKPILEUnk; + using OpenSHC::Map::LogicHelpers::L_WALL_OR_GATEHOUSE; + + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x004F8840 + BOOLEnum TileMapState::isWallConnectionHeightValid(int tile, int y, int param_3) + { + int tileHeight = this->HeightLayer[tile]; + int firstDirection = 0; + int secondDirection = 0; + if (param_3 == 0) { + secondDirection = 4; + } else if (param_3 == 2) { + firstDirection = 2; + secondDirection = 6; + } else if (param_3 == 4) { + secondDirection = param_3; + } else if (param_3 == 6) { + firstDirection = 2; + secondDirection = 6; + } + + int first = this->directionTranslationMatrix[y][firstDirection] + tile; + if ((this->LogicLayer[first] & L_WALL_OR_GATEHOUSE) == 0) { + return FALSE; + } + if ((this->LogicLayer[first] & L_STOCKPILEUnk) != 0) { + return FALSE; + } + int minHeight = tileHeight - 0x10; + if (this->HeightLayer[first] < minHeight && this->DamageLayer[first] == 0) { + return FALSE; + } + + int second = this->directionTranslationMatrix[y][secondDirection] + tile; + if ((this->LogicLayer[second] & L_WALL_OR_GATEHOUSE) == 0) { + return FALSE; + } + if ((this->LogicLayer[second] & L_STOCKPILEUnk) != 0) { + return FALSE; + } + if (this->HeightLayer[second] < minHeight && this->DamageLayer[second] == 0) { + return FALSE; + } + return TRUE; + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/isWallCornerForCardinalDirection.cpp b/src/OpenSHC/Map/TileMapState/isWallCornerForCardinalDirection.cpp new file mode 100644 index 0000000000..bf687ee3a7 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/isWallCornerForCardinalDirection.cpp @@ -0,0 +1,54 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_CRENEL; + + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x004F86D0 + BOOLEnum TileMapState::isWallCornerForCardinalDirection(int tile, int y, int direction) + { + int first = 0; + int second = 0; + int third = 0; + int fourth = 0; + if (direction == 0) { + first = 0; + second = 4; + third = 2; + fourth = 6; + } else if (direction == 2) { + first = 2; + second = 6; + third = 0; + fourth = 4; + } else if (direction == 4) { + first = 0; + second = 4; + third = 2; + fourth = 6; + } else if (direction == 6) { + first = 2; + second = 6; + third = 0; + fourth = 4; + } + + if ((this->LogicLayer[this->directionTranslationMatrix[y][first] + tile] & L_CRENEL) == 0) { + return FALSE; + } + if ((this->LogicLayer[this->directionTranslationMatrix[y][second] + tile] & L_CRENEL) == 0) { + return FALSE; + } + if ((this->LogicLayer[this->directionTranslationMatrix[y][third] + tile] & L_CRENEL) != 0) { + return FALSE; + } + return ~(this->LogicLayer[this->directionTranslationMatrix[y][fourth] + tile] >> 9) & TRUE; + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/isWallCornerForDiagonalDirection.cpp b/src/OpenSHC/Map/TileMapState/isWallCornerForDiagonalDirection.cpp new file mode 100644 index 0000000000..9102067b61 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/isWallCornerForDiagonalDirection.cpp @@ -0,0 +1,50 @@ +#include "../TileMapState.func.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_CRENEL; + + // FUNCTION: STRONGHOLDCRUSADER 0x004F8780 + uint TileMapState::isWallCornerForDiagonalDirection(int tile, int y, int direction) + { + int first = 0; + int second = 0; + int third = 0; + int fourth = 0; + if (direction == 1) { + first = 4; + second = 6; + third = 0; + fourth = 2; + } else if (direction == 3) { + first = 0; + second = 6; + third = 4; + fourth = 2; + } else if (direction == 5) { + first = 0; + second = 2; + third = 4; + fourth = 6; + } else if (direction == 7) { + first = 4; + second = 2; + third = 0; + fourth = 6; + } + + if ((this->LogicLayer[this->directionTranslationMatrix[y][first] + tile] & L_CRENEL) == 0) { + return 0; + } + if ((this->LogicLayer[this->directionTranslationMatrix[y][second] + tile] & L_CRENEL) == 0) { + return 0; + } + if ((this->LogicLayer[this->directionTranslationMatrix[y][third] + tile] & L_CRENEL) != 0) { + return 0; + } + return ~((uint)this->LogicLayer[this->directionTranslationMatrix[y][fourth] + tile] >> 9) & 1; + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/markBuildingFootprintFlag.cpp b/src/OpenSHC/Map/TileMapState/markBuildingFootprintFlag.cpp new file mode 100644 index 0000000000..3d00eac4c9 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/markBuildingFootprintFlag.cpp @@ -0,0 +1,26 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_PLAIN1_AND_FARM; + + // FUNCTION: STRONGHOLDCRUSADER 0x004FA9D0 + void TileMapState::markBuildingFootprintFlag(int param_1, int param_2, int param_3) + { + int buildingSizeTileIndex = 0; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)( + buildingSizeTileIndex, param_3); + buildingSizeTileIndex++; + int tile = DAT_ViewportRenderState::instance.translationMatrix[this->buildingY + param_2].addXgetTile + + this->buildingX + param_1; + this->LogicLayer[tile] = this->LogicLayer[tile] | L_PLAIN1_AND_FARM; + this->MiscDisplayLayer[tile] = this->MiscDisplayLayer[tile] & 0xfff3; + } while (buildingSizeTileIndex < this->constructionTileCount); + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/noop1.cpp b/src/OpenSHC/Map/TileMapState/noop1.cpp new file mode 100644 index 0000000000..ea3d3f93c3 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/noop1.cpp @@ -0,0 +1,10 @@ +#include "../TileMapState.func.hpp" + +namespace OpenSHC { +namespace Map { + + // FUNCTION: STRONGHOLDCRUSADER 0x004F70D0 + void TileMapState::noop1(undefined4 param_1) { return; } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/placeApplefarm.cpp b/src/OpenSHC/Map/TileMapState/placeApplefarm.cpp new file mode 100644 index 0000000000..8795083ebe --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/placeApplefarm.cpp @@ -0,0 +1,87 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Map/Buildings/BuildingsState.func.hpp" +#include "OpenSHC/Map/LandscapeState.func.hpp" +#include "OpenSHC/UI/BottomLeftTextDisplayState.func.hpp" +#include "OpenSHC/Map/Buildings/BuildingType.hpp" +#include "OpenSHC/Map/LogicHelpers/Logic1.hpp" +#include "OpenSHC/Map/LogicHelpers/Logic2.hpp" + +#include "OpenSHC/Globals/DAT_BottomLeftTextDisplayState.hpp" +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_GameState.hpp" +#include "OpenSHC/Globals/DAT_GameSynchronyState.hpp" +#include "OpenSHC/Globals/DAT_LandscapeState.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::Buildings::BuildingType; + using OpenSHC::Map::LogicHelpers::L_BUILDING; + using OpenSHC::Map::LogicHelpers::L_FARM_FIELD_APPLE; + using OpenSHC::Map::LogicHelpers::L_NONE; + using OpenSHC::Map::LogicHelpers::L2_THICK_SCRUB; + + // FUNCTION: STRONGHOLDCRUSADER 0x00515740 + void TileMapState::placeApplefarm( + int playerID, uint x, uint y, BuildingType buildingType, undefined4 param_5, int variation, int* averageHeight) + { + int index = 0; + int buildingID = MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::setupBuildingData, + DAT_BuildingsState::ptr)(playerID, x, y, (undefined4)averageHeight, (BuildingType)(short)buildingType, 3, + playerID, variation); + this->placedBuildingID = buildingID; + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::markBuildingFootprintFlag, this)(x, y, 10); + + /* the 8 apple tree tiles */ + for (int i = 0; i < 8; i++) { + DAT_BuildingsState::instance.buildings[buildingID].tileRefs[i] + = DAT_ViewportRenderState::instance + .translationMatrix[DAT_TerrainDefinedData::instance.AppleFarmOffsets[i].y + y] + .addXgetTile + + DAT_TerrainDefinedData::instance.AppleFarmOffsets[i].x + x; + } + + /* the farm house */ + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)(index, 3); + int tileUnk = DAT_ViewportRenderState::instance.translationMatrix[this->buildingY + y].addXgetTile + x + + this->buildingX; + this->HeightLayer[tileUnk] = (byte)(int)averageHeight; + this->LogicLayer[tileUnk] = this->LogicLayer[tileUnk] | L_BUILDING; + this->BuildingLayer[tileUnk] = (short)buildingID; + this->BuildingWasLayer[tileUnk] = (uchar)buildingType; + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::setTerrain, this)( + playerID, tileUnk, this->buildingY + y, 2, L_NONE, L2_THICK_SCRUB); + index++; + this->ChangedLayer[tileUnk] = 2; + } while (index < this->constructionTileCount); + + for (int i = 0; i < 8; i++) { + int tileUnk = DAT_BuildingsState::instance.buildings[buildingID].tileRefs[i]; + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::resetTileAndClearMoat, this)(tileUnk); + this->LogicLayer[tileUnk] = this->LogicLayer[tileUnk] | L_FARM_FIELD_APPLE; + this->ChangedLayer[tileUnk] = 2; + MACRO_CALL_MEMBER(OpenSHC::Map::LandscapeState_Func::placeAppleTree, DAT_LandscapeState::ptr)(buildingID, + DAT_TerrainDefinedData::instance.AppleFarmOffsets[i].x + x, + DAT_TerrainDefinedData::instance.AppleFarmOffsets[i].y + y); + } + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::setMiscDisplayLayer, this)(buildingID); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::updatePathLinkagesForBuilding, this)(buildingID); + + /* not enough idle peasants for the workers: tell the local player */ + if (playerID == DAT_GameSynchronyState::instance.currentPlayerSlotID + && DAT_BuildingsState::instance.buildings[buildingID].buildingTypeBasedEmployeeCount + > DAT_GameState::instance.playerDataArray[playerID].availablePeasantsAtFire + && (DAT_GameState::instance.playerDataArray[playerID].populationCap + <= DAT_GameState::instance.playerDataArray[playerID].currentPopulation + || DAT_GameState::instance.playerDataArray[playerID].popularity < 5000)) { + MACRO_CALL_MEMBER(OpenSHC::UI::BottomLeftTextDisplayState_Func::setBottomLeftTextDisplayText, + DAT_BottomLeftTextDisplayState::ptr)(1, 0x4d, 1, 0, 100, 6000); + } + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/placeBarracks.cpp b/src/OpenSHC/Map/TileMapState/placeBarracks.cpp new file mode 100644 index 0000000000..1d5ee5768f --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/placeBarracks.cpp @@ -0,0 +1,170 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Map/Buildings/BuildingsState.func.hpp" +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" +#include "OpenSHC/UI/BottomLeftTextDisplayState.func.hpp" +#include "OpenSHC/Map/Buildings/BuildingType.hpp" + +#include "OpenSHC/Globals/DAT_BottomLeftTextDisplayState.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" +#include "OpenSHC/Globals/DAT_PathFindingState.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::Buildings::BuildingType; + + // FUNCTION: STRONGHOLDCRUSADER 0x005076A0 + void TileMapState::placeBarracks(int playerID, uint xPosition, int* yPosition_param, undefined4 buildingType, + uint buildingSize, int buildingOrientation, undefined4 param_7) + { + int* piVar1; + int _buildingID; + int iVar2; + int iVar3; + uint uVar4; + int iVar5; + uint uVar6; + int iVar7; + int local_c; + piVar1 = yPosition_param; + iVar7 = DAT_GameCore::instance.uniqueGameObjectTracker; + iVar5 = 0; + if (buildingOrientation == 0xf) { + local_c = 0; + } else { + local_c = buildingOrientation / 2; + } + _buildingID = MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::setupBuildingData, + DAT_BuildingsState::ptr)(playerID, xPosition, (uint)(yPosition_param), (undefined4)((int)(param_7)), + (BuildingType)((int)((short)buildingType)), buildingSize, playerID, 0xf); + iVar2 = (int)(short)_buildingID; + this->placedBuildingID = iVar2; + DAT_BuildingsState::instance.buildings[iVar2].uidWhenPlaced = iVar7; + yPosition_param = &DAT_BuildingsState::instance.buildings[iVar2].tileRefs[0]; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)( + iVar5, (int)(buildingSize)); + iVar3 = DAT_ViewportRenderState::instance.translationMatrix[this->buildingY + (int)piVar1].addXgetTile + + this->buildingX + xPosition; + *yPosition_param = iVar3; + this->HeightLayer[iVar3] = (byte)param_7; + this->LogicLayer[iVar3] = this->LogicLayer[iVar3] | 0x400; + this->BuildingLayer[iVar3] = (short)_buildingID; + iVar5 = iVar5 + 1; + yPosition_param = yPosition_param + 1; + this->BuildingWasLayer[iVar3] = (uchar)buildingType; + this->ChangedLayer[iVar3] = 2; + } while (iVar5 < this->constructionTileCount); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::setMiscDisplayLayer, this)(iVar2); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::updatePathLinkagesForBuilding, this)(iVar2); + uVar6 = (int)piVar1 + DAT_TerrainDefinedData::instance.BuildingPartsOffsets[local_c][0].y; + uVar4 = xPosition + DAT_TerrainDefinedData::instance.BuildingPartsOffsets[local_c][0].x; + iVar5 = MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::setupBuildingData, DAT_BuildingsState::ptr)(playerID, uVar4, + uVar6, (undefined4)((int)(param_7)), OpenSHC::Map::Buildings::BT_PARADEGROUND3, 5, playerID, 0xf); + _buildingID = (int)(short)iVar5; + DAT_BuildingsState::instance.buildings[_buildingID].uidWhenPlaced = iVar7; + DAT_BuildingsState::instance.buildings[_buildingID].quarryStockpileID = (undefined2)this->placedBuildingID; + buildingSize = 0; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)( + buildingSize, (int)(DAT_BuildingsState::instance.buildings[_buildingID].widthOrHeight)); + iVar2 = DAT_ViewportRenderState::instance.translationMatrix[this->buildingY + uVar6].addXgetTile + + this->buildingX + uVar4; + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::resetTileAndClearMoat, this)(iVar2); + this->HeightLayer[iVar2] = (byte)param_7; + if ((this->buildingX == 2) && (this->buildingY == 2)) { + this->LogicLayer[iVar2] = this->LogicLayer[iVar2] | 0x400; + } + this->BuildingLayer[iVar2] = (short)iVar5; + buildingSize = buildingSize + 1; + this->BuildingWasLayer[iVar2] = (uchar)buildingType; + this->ChangedLayer[iVar2] = 2; + } while ((int)buildingSize < this->constructionTileCount); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::setMiscDisplayLayer, this)(_buildingID); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::updatePathLinkagesForBuilding, this)(_buildingID); + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::updateWalkAndPathLayer, + DAT_PathFindingState::ptr)(8, uVar4, uVar6); + uVar6 = DAT_TerrainDefinedData::instance.BuildingPartsOffsets[local_c][1].y + (int)piVar1; + uVar4 = DAT_TerrainDefinedData::instance.BuildingPartsOffsets[local_c][1].x + xPosition; + iVar5 = MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::setupBuildingData, DAT_BuildingsState::ptr)(playerID, uVar4, + uVar6, (undefined4)((int)(param_7)), OpenSHC::Map::Buildings::BT_PARADEGROUND4, 5, playerID, 0xf); + _buildingID = (int)(short)iVar5; + DAT_BuildingsState::instance.buildings[_buildingID].uidWhenPlaced = iVar7; + DAT_BuildingsState::instance.buildings[_buildingID].quarryStockpileID = (undefined2)this->placedBuildingID; + buildingSize = 0; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)( + buildingSize, (int)(DAT_BuildingsState::instance.buildings[_buildingID].widthOrHeight)); + iVar2 = DAT_ViewportRenderState::instance.translationMatrix[this->buildingY + uVar6].addXgetTile + + this->buildingX + uVar4; + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::resetTileAndClearMoat, this)(iVar2); + this->HeightLayer[iVar2] = (byte)param_7; + if ((this->buildingX == 2) && (this->buildingY == 2)) { + this->LogicLayer[iVar2] = this->LogicLayer[iVar2] | 0x400; + } + this->BuildingLayer[iVar2] = (short)iVar5; + buildingSize = buildingSize + 1; + this->BuildingWasLayer[iVar2] = (uchar)buildingType; + this->ChangedLayer[iVar2] = 2; + } while ((int)buildingSize < this->constructionTileCount); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::setMiscDisplayLayer, this)(_buildingID); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::updatePathLinkagesForBuilding, this)(_buildingID); + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::updateWalkAndPathLayer, + DAT_PathFindingState::ptr)(8, uVar4, uVar6); + uVar6 = DAT_TerrainDefinedData::instance.BuildingPartsOffsets[local_c][2].y + (int)piVar1; + uVar4 = DAT_TerrainDefinedData::instance.BuildingPartsOffsets[local_c][2].x + xPosition; + iVar5 = MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::setupBuildingData, DAT_BuildingsState::ptr)(playerID, uVar4, + uVar6, (undefined4)((int)(param_7)), OpenSHC::Map::Buildings::BT_PARADEGROUND2, 5, playerID, 0xf); + _buildingID = (int)(short)iVar5; + DAT_BuildingsState::instance.buildings[_buildingID].uidWhenPlaced = iVar7; + DAT_BuildingsState::instance.buildings[_buildingID].quarryStockpileID = (undefined2)this->placedBuildingID; + buildingSize = 0; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)( + buildingSize, (int)(DAT_BuildingsState::instance.buildings[_buildingID].widthOrHeight)); + iVar7 = DAT_ViewportRenderState::instance.translationMatrix[this->buildingY + uVar6].addXgetTile + + this->buildingX + uVar4; + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::resetTileAndClearMoat, this)(iVar7); + this->HeightLayer[iVar7] = (byte)param_7; + if ((this->buildingX == 2) && (this->buildingY == 2)) { + this->LogicLayer[iVar7] = this->LogicLayer[iVar7] | 0x400; + } + this->BuildingLayer[iVar7] = (short)iVar5; + this->BuildingWasLayer[iVar7] = (uchar)buildingType; + buildingSize = buildingSize + 1; + this->ChangedLayer[iVar7] = 2; + } while ((int)buildingSize < this->constructionTileCount); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::setMiscDisplayLayer, this)(_buildingID); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::updatePathLinkagesForBuilding, this)(_buildingID); + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::updateWalkAndPathLayer, + DAT_PathFindingState::ptr)(8, uVar4, uVar6); + if ((short)buildingType == 8) { + MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::setupMercenaryPostCampgroundPositions, + DAT_BuildingsState::ptr)(playerID); + } else { + MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::setupBarracksCampgroundPositions, + DAT_BuildingsState::ptr)(playerID); + } + if (playerID == DAT_GameSynchronyState::instance.currentPlayerSlotID + && DAT_GameState::instance.playerDataArray[playerID].availablePeasantsAtFire + < (int)DAT_BuildingsState::instance.buildings[_buildingID].buildingTypeBasedEmployeeCount + && (DAT_GameState::instance.playerDataArray[playerID].populationCap + <= DAT_GameState::instance.playerDataArray[playerID].currentPopulation + || (DAT_GameState::instance.playerDataArray[playerID].popularity < 5000))) { + MACRO_CALL_MEMBER(OpenSHC::UI::BottomLeftTextDisplayState_Func::setBottomLeftTextDisplayText, + DAT_BottomLeftTextDisplayState::ptr)(1, 0x4d, 1, 0, 100, 6000); + } + return; + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/placeBuilding.cpp b/src/OpenSHC/Map/TileMapState/placeBuilding.cpp new file mode 100644 index 0000000000..243eb0418b --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/placeBuilding.cpp @@ -0,0 +1,344 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Game.func.hpp" +#include "OpenSHC/Map/Buildings/BuildingsState.func.hpp" +#include "OpenSHC/Map/LandscapeState.func.hpp" +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" +#include "OpenSHC/Map/Units/TribesState.func.hpp" +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Map/WallAndPitchState.func.hpp" +#include "OpenSHC/UI/Helpers.func.hpp" +#include "OpenSHC/UI/MinimapViewState.func.hpp" +#include "OpenSHC/Commands/MappersEnum.hpp" +#include "OpenSHC/Game/GameMode.hpp" +#include "OpenSHC/Game/GameMode2.hpp" +#include "OpenSHC/Map/Buildings/BuildingType.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" +#include "OpenSHC/Globals/DAT_LandscapeState.hpp" +#include "OpenSHC/Globals/DAT_MinimapViewState.hpp" +#include "OpenSHC/Globals/DAT_PathFindingState.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_TribesState.hpp" +#include "OpenSHC/Globals/DAT_UnitsState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" +#include "OpenSHC/Globals/DAT_WallAndPitchState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_CRENEL; + using OpenSHC::Map::LogicHelpers::L_CRENEL_VARIATIONUnk; + using OpenSHC::Map::LogicHelpers::L_MOAT; + using OpenSHC::Map::LogicHelpers::L_MOAT_DUG_OR_PLANNED; + using OpenSHC::Map::LogicHelpers::L_PLAIN2_AND_PITCH; + using OpenSHC::Map::LogicHelpers::L_ROCKY; + using OpenSHC::Map::LogicHelpers::L_STAIRS; + using OpenSHC::Map::LogicHelpers::L_TREE; + using OpenSHC::Map::LogicHelpers::L_UNKNOWN_WALL_RELATED; + using OpenSHC::Map::LogicHelpers::L_WALL_OR_GATEHOUSE; + + using OpenSHC::Commands::MappersEnum; + using OpenSHC::Game::GameMode; + using OpenSHC::Game::GameMode2; + using OpenSHC::Map::Buildings::BuildingType; + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x005162D0 + void TileMapState::placeBuilding( + int playerID, int x, int y, MappersEnum cbt, int buildingSize, int buildingOrientation) + { + MappersEnum command = (MappersEnum)(short)cbt; + int pitchDitchID = 0; + if (this->skipPlacementCheck == 0) { + if (buildingOrientation == 0xf) { + this->DAT_TempBuildingRotation = 0; + } else { + this->DAT_TempBuildingRotation = buildingOrientation / 2; + } + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::checkBuildingCanBePlacedHere, this)( + playerID, x, y, cbt, buildingSize); + if (this->buildingPlacementFail != FALSE) { + return; + } + } + this->skipPlacementCheck = 0; + + BuildingType buildingType + = MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::convertCommandBuildingTypeToBuildingType, + DAT_BuildingsState::ptr)(command); + short shortType = (short)buildingType; + if (DAT_GameCore::instance.gameMode_2 == OpenSHC::Game::GM_CRUSADER_TUTORIAL) { + if (MACRO_CALL(OpenSHC::Game_Func::Tutorial_IsActionAllowed)(2, (short)shortType) == FALSE) { + MACRO_CALL(OpenSHC::UI::Helpers_Func::SetTutorialHintActiveWithTimestamp)(); + return; + } + MACRO_CALL(OpenSHC::UI::Helpers_Func::SetTutorialBuildingActionState)( + 7, (BuildingType)(int)(short)shortType); + } + + /* clear whatever the footprint was before the building goes down */ + int index = 0; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)( + index, buildingSize); + int tile = DAT_ViewportRenderState::instance.translationMatrix[this->buildingY + y].addXgetTile + + this->buildingX + x; + if (DAT_GameCore::instance.gameMode_2 == OpenSHC::Game::GM_SIEGE_THAT + && (this->LogicLayer[tile] & L_WALL_OR_GATEHOUSE) != 0) { + DAT_GameState::instance.playerDataArray[playerID].startResources[4] + = DAT_GameState::instance.playerDataArray[playerID].startResources[4] + 1; + } + if ((this->LogicLayer[tile] & L_ROCKY) != 0 && this->OrganismLayer[tile] > 1999) { + MACRO_CALL_MEMBER(OpenSHC::Map::LandscapeState_Func::removeRock, DAT_LandscapeState::ptr)( + this->OrganismLayer[tile] - 2000); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)( + index, buildingSize); + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::updateWalkAndPathLayer, + DAT_PathFindingState::ptr)(8, this->buildingX + x, this->buildingY + y); + } + this->LogicLayer[tile] = this->LogicLayer[tile] + & ~(L_CRENEL_VARIATIONUnk | L_UNKNOWN_WALL_RELATED | L_STAIRS | L_CRENEL | L_WALL_OR_GATEHOUSE + | L_PLAIN2_AND_PITCH); + this->HeightLayer[tile] = DAT_TileMapState::instance.DefaultHeightLayer[tile]; + this->DamageLayer[tile] = 0; + if ((this->LogicLayer[tile] & L_TREE) != 0 && this->OrganismLayer[tile] < 2000) { + /* every tree goes, scrub or not; only the reported reason differs */ + MACRO_CALL_MEMBER(OpenSHC::Map::LandscapeState_Func::removeTree, DAT_LandscapeState::ptr)( + this->OrganismLayer[tile]); + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::updateWalkAndPathLayer, + DAT_PathFindingState::ptr)(3, x, y); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)( + index, buildingSize); + } + if ((short)this->UnitLayer[tile] != 0) { + /* a unit standing where a walkable building goes is left alone */ + switch (shortType) { + case OpenSHC::Map::Buildings::BT_GATEHOUSELARGE: + case OpenSHC::Map::Buildings::BT_GATEHOUSESMALL: + case OpenSHC::Map::Buildings::BT_DRAWBRIDGE: + case OpenSHC::Map::Buildings::BT_CAMPFIRE: + case OpenSHC::Map::Buildings::BT_PARADEGROUND: + case OpenSHC::Map::Buildings::BT_CAMPGROUND: + case OpenSHC::Map::Buildings::BT_PARADEGROUND2: + case OpenSHC::Map::Buildings::BT_PARADEGROUND3: + case OpenSHC::Map::Buildings::BT_PARADEGROUND4: + case OpenSHC::Map::Buildings::BT_PARADEGROUND5: + case OpenSHC::Map::Buildings::BT_KILLINGPIT: + case OpenSHC::Map::Buildings::BT_PITCHDITCH: + case OpenSHC::Map::Buildings::BT_SIEGETOWER_PLACED: + 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: + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::deleteUnit, DAT_UnitsState::ptr)( + (short)this->UnitLayer[tile]); + } + } + if ((this->LogicLayer[tile] & (L_MOAT | L_MOAT_DUG_OR_PLANNED)) != 0) { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::clearMoatDataAtTile, this)( + this->buildingX + x, this->buildingY + y); + this->LogicLayer[tile] = this->LogicLayer[tile] & ~(L_MOAT | L_MOAT_DUG_OR_PLANNED); + } + this->MiscDisplayLayer[tile] = this->MiscDisplayLayer[tile] & 0xfc3f; + index++; + DAT_PathFindingState::instance.toggleUpdateSeparateAreaTileMap = 1; + DAT_TileMapState::instance.field204_0x554a30 = 1; + } while (index < this->constructionTileCount); + + /* the building sits at the middle of the heights it covers */ + uint highest = 0; + uint lowest = 1000; + index = 0; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)( + index, buildingSize); + uint tileHeight + = this->HeightLayer[DAT_ViewportRenderState::instance.translationMatrix[this->buildingY + y].addXgetTile + + this->buildingX + x]; + if (highest < tileHeight) { + highest = tileHeight; + } + if (tileHeight < lowest) { + lowest = tileHeight; + } + index++; + } while (index < this->constructionTileCount); + int averageHeight = (highest - lowest) / 2 + lowest; + + if (shortType == OpenSHC::Map::Buildings::BT_TUNNEL + && playerID == DAT_GameSynchronyState::instance.currentPlayerSlotID) { + MACRO_CALL_MEMBER(OpenSHC::Map::Units::TribesState_Func::playTunnelerCommandSpeech, DAT_TribesState::ptr)(); + } + + switch ((int)shortType) { + case OpenSHC::Map::Buildings::BT_MERCENARYPOST: + case OpenSHC::Map::Buildings::BT_BARRACKS: + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::placeBarracks, this)( + playerID, x, (int*)y, buildingType, buildingSize, buildingOrientation, averageHeight); + break; + case OpenSHC::Map::Buildings::BT_STOCKPILE: + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::placeStockpile, this)( + playerID, x, y, buildingType, buildingSize, buildingOrientation, averageHeight); + break; + default: + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::placeWorkshopOrHovel, this)( + playerID, x, y, buildingType, buildingSize, buildingOrientation, averageHeight); + break; + case OpenSHC::Map::Buildings::BT_QUARRY: + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::placeQuarry, this)( + playerID, x, y, buildingType, buildingSize, buildingOrientation, averageHeight); + break; + case OpenSHC::Map::Buildings::BT_ENGINEERSGUILD: + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::placeEngineersguild, this)( + playerID, (int*)x, y, buildingType, buildingSize, buildingOrientation, averageHeight); + break; + case OpenSHC::Map::Buildings::BT_TUNNELERSGUILD: + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::placeTunnelersguild, this)( + playerID, (int*)x, y, buildingType, buildingSize, buildingOrientation, averageHeight); + break; + case OpenSHC::Map::Buildings::BT_OILSMELTER: + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::placeOilsmelter, this)( + playerID, x, y, buildingType, buildingSize, buildingOrientation, averageHeight); + break; + case OpenSHC::Map::Buildings::BT_WHEATFARM: + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::placeWheatfarm, this)( + playerID, x, y, buildingType, buildingSize, buildingOrientation, averageHeight); + break; + case OpenSHC::Map::Buildings::BT_HOPFARM: + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::placeHopfarm, this)( + playerID, x, y, buildingType, buildingSize, buildingOrientation, averageHeight); + break; + case OpenSHC::Map::Buildings::BT_APPLEFARM: + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::placeApplefarm, this)( + playerID, x, y, buildingType, buildingSize, buildingOrientation, (int*)averageHeight); + break; + case OpenSHC::Map::Buildings::BT_DAIRYFARM: + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::placeDairyfarm, this)( + playerID, x, y, buildingType, buildingSize, (int*)buildingOrientation, averageHeight); + break; + case OpenSHC::Map::Buildings::BT_GATEHOUSELARGE: + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::placeGatehouseLarge, this)( + playerID, x, y, buildingType, buildingSize, buildingOrientation, averageHeight); + break; + case OpenSHC::Map::Buildings::BT_GATEHOUSESMALL: + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::placeGatehouseSmall, this)( + playerID, x, y, buildingType, buildingSize, buildingOrientation, averageHeight); + break; + case OpenSHC::Map::Buildings::BT_DRAWBRIDGE: + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::placeDrawbridge, this)( + playerID, x, y, buildingType, buildingSize, (int*)buildingOrientation, averageHeight); + break; + case OpenSHC::Map::Buildings::BT_FIREBALLISTA: + case OpenSHC::Map::Buildings::BT_CATAPULT: + case OpenSHC::Map::Buildings::BT_TREBUCHET: + case OpenSHC::Map::Buildings::BT_BATTERINGRAM: + case OpenSHC::Map::Buildings::BT_SIEGETOWER: + case OpenSHC::Map::Buildings::BT_SHIELD: + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::placeSiegeTent, this)( + playerID, x, y, buildingType, buildingSize, buildingOrientation, averageHeight); + break; + case OpenSHC::Map::Buildings::BT_KILLINGPIT: + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::placeKillingPit, this)( + playerID, x, y, buildingType, buildingSize, buildingOrientation, averageHeight); + break; + case OpenSHC::Map::Buildings::BT_SIEGETOWER_PLACED: + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::placeSiegetowerPlaced, this)( + playerID, x, y, buildingType, buildingSize, buildingOrientation, averageHeight); + break; + 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: + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::placeTower, this)( + playerID, x, y, buildingType, buildingSize, buildingOrientation, averageHeight); + break; + case OpenSHC::Map::Buildings::BT_UNKNOWN1: + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::stampBuildingOntoTileMap, this)(playerID, x, y, + buildingType, command + ~OpenSHC::Commands::M_MAPPER_MP_KEEP8, buildingSize, buildingOrientation, + averageHeight); + break; + 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: + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::placeKeep, this)( + playerID, x, y, buildingType, buildingSize, buildingOrientation, averageHeight); + break; + case OpenSHC::Map::Buildings::BT_WOODGATE1: + break; + case OpenSHC::Map::Buildings::BT_PITCHDITCH: + pitchDitchID = MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::placePitchDitch, this)(playerID, x, y); + break; + case OpenSHC::Map::Buildings::BT_GARDEN: + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::placePositiveFearfactor, this)(playerID, x, y, + buildingType, command - OpenSHC::Commands::M_MAPPER_GARDEN1, buildingSize, buildingOrientation, + averageHeight); + break; + case OpenSHC::Map::Buildings::BT_CESSPIT: + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::placePositiveFearfactor, this)(playerID, x, y, + buildingType, command - OpenSHC::Commands::M_MAPPER_CESS_PIT1, buildingSize, buildingOrientation, + averageHeight); + break; + case OpenSHC::Map::Buildings::BT_STATUE: + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::placePositiveFearfactor, this)(playerID, x, y, + buildingType, command - OpenSHC::Commands::M_MAPPER_STATUE1, buildingSize, buildingOrientation, + averageHeight); + break; + case OpenSHC::Map::Buildings::BT_SHRINE: + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::placePositiveFearfactor, this)(playerID, x, y, + buildingType, command - OpenSHC::Commands::M_MAPPER_SHRINE1, buildingSize, buildingOrientation, + averageHeight); + break; + case OpenSHC::Map::Buildings::BT_POND: + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::placePositiveFearfactor, this)(playerID, x, y, + buildingType, command - OpenSHC::Commands::M_MAPPER_POND1, buildingSize, buildingOrientation, + averageHeight); + break; + } + + if (playerID == DAT_GameSynchronyState::instance.currentPlayerSlotID) { + if (shortType != OpenSHC::Map::Buildings::BT_PITCHDITCH) { + MACRO_CALL_MEMBER(OpenSHC::Map::WallAndPitchState_Func::startBuildingDestructionConfirmation, + DAT_WallAndPitchState::ptr)(this->placedBuildingID); + } else if (pitchDitchID != 0) { + MACRO_CALL_MEMBER(OpenSHC::Map::WallAndPitchState_Func::placePitchDitch, DAT_WallAndPitchState::ptr)( + pitchDitchID); + } + } + MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::processPlacementResourceLossForBuildingType, + DAT_BuildingsState::ptr)(playerID, (BuildingType)(int)(short)shortType, 0); + if (MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::hasLessWoodThanTheCostOfAWoodcuttersHutAndNoWoodcutters, + DAT_BuildingsState::ptr)(playerID, (int)(short)shortType) + != 0) { + DAT_BuildingsState::instance.buildings[this->placedBuildingID].suppressDestroyRefund = 1; + } + MACRO_CALL_MEMBER(OpenSHC::UI::MinimapViewState_Func::triggerMinimapRedraw, DAT_MinimapViewState::ptr)(1); + int radius; + if (buildingSize < 6) { + radius = 9; + } else { + radius = buildingSize + 5; + } + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::updateWalkAndPathLayer, + DAT_PathFindingState::ptr)(radius, x, y); + DAT_PathFindingState::instance.toggleUpdateSeparateAreaTileMap = 1; + DAT_TileMapState::instance.field204_0x554a30 = 1; + if (DAT_GameSynchronyState::instance.currentGameMode == OpenSHC::Game::GM_SOLITARY) { + this->forceUpdateMacroLayerFlag = 1; + this->field68_0x55487c = 200; + } + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/placeDairyfarm.cpp b/src/OpenSHC/Map/TileMapState/placeDairyfarm.cpp new file mode 100644 index 0000000000..7edd8d40eb --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/placeDairyfarm.cpp @@ -0,0 +1,107 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Map/Buildings/BuildingsState.func.hpp" +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" +#include "OpenSHC/UI/BottomLeftTextDisplayState.func.hpp" +#include "OpenSHC/Map/Buildings/BuildingType.hpp" +#include "OpenSHC/Map/LogicHelpers/Logic1.hpp" +#include "OpenSHC/Map/LogicHelpers/Logic2.hpp" + +#include "OpenSHC/Globals/DAT_BottomLeftTextDisplayState.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_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::Buildings::BuildingType; + using OpenSHC::Map::LogicHelpers::L_BUILDING; + using OpenSHC::Map::LogicHelpers::L_FARM_FIELD_DAIRY; + using OpenSHC::Map::LogicHelpers::L_NONE; + using OpenSHC::Map::LogicHelpers::L2_THICK_SCRUB; + + // FUNCTION: STRONGHOLDCRUSADER 0x005154D0 + void TileMapState::placeDairyfarm(int playerID, uint x, uint y, undefined4 buildingType, undefined4 param_5, + int* variation, undefined4 averageHeight) + { + int index = 0; + int buildingID = MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::setupBuildingData, + DAT_BuildingsState::ptr)(playerID, x, y, averageHeight, (BuildingType)(short)buildingType, 3, playerID, + (int)variation); + this->placedBuildingID = buildingID; + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::markBuildingFootprintFlag, this)(x, y, 10); + + /* 27 tiles from one of four layouts; tiles 4.. are the field and carry an initial crop stage */ + for (int i = 0; i < 27; i++) { + DAT_BuildingsState::instance.buildings[buildingID].tileRefs[i] + = DAT_ViewportRenderState::instance + .translationMatrix[DAT_TerrainDefinedData::instance + .field878_0xf5c[DAT_GameState::instance.playerDataArray[playerID] + .dairyFarmVariationMod4][i] + .offset.y + + y] + .addXgetTile + + DAT_TerrainDefinedData::instance + .field878_0xf5c[DAT_GameState::instance.playerDataArray[playerID].dairyFarmVariationMod4][i] + .offset.x + + x; + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::resetTileAndClearMoat, this)( + DAT_BuildingsState::instance.buildings[buildingID].tileRefs[i]); + if (i >= 4) { + this->DamageLayer[DAT_BuildingsState::instance.buildings[buildingID].tileRefs[i]] + = (byte)DAT_TerrainDefinedData::instance + .field878_0xf5c[DAT_GameState::instance.playerDataArray[playerID].dairyFarmVariationMod4] + [i] + .property; + } + } + DAT_GameState::instance.playerDataArray[playerID].dairyFarmVariationMod4++; + if (DAT_GameState::instance.playerDataArray[playerID].dairyFarmVariationMod4 > 3) { + DAT_GameState::instance.playerDataArray[playerID].dairyFarmVariationMod4 = 0; + } + + /* the farm house */ + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)(index, 3); + int tileUnk = DAT_ViewportRenderState::instance.translationMatrix[this->buildingY + y].addXgetTile + + this->buildingX + x; + this->HeightLayer[tileUnk] = (byte)averageHeight; + this->LogicLayer[tileUnk] = this->LogicLayer[tileUnk] | L_BUILDING; + this->BuildingLayer[tileUnk] = (short)buildingID; + this->BuildingWasLayer[tileUnk] = (uchar)buildingType; + this->ChangedLayer[tileUnk] = 2; + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::setTerrain, this)( + playerID, tileUnk, this->buildingY + y, 2, L_NONE, L2_THICK_SCRUB); + index++; + } while (index < this->constructionTileCount); + + for (int i = 4; i < 27; i++) { + int tileUnk = DAT_BuildingsState::instance.buildings[buildingID].tileRefs[i]; + this->LogicLayer[tileUnk] = this->LogicLayer[tileUnk] | L_FARM_FIELD_DAIRY; + this->BuildingLayer[tileUnk] = (short)buildingID; + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::updatePathLinkagesInAllEightDirections, + DAT_PathFindingState::ptr)(DAT_ViewportRenderState::instance.tileTranslationMatrix_YComponent[tileUnk], tileUnk); + this->BuildingWasLayer[tileUnk] = (uchar)buildingType; + this->ChangedLayer[tileUnk] = 2; + } + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::setMiscDisplayLayer, this)(buildingID); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::updatePathLinkagesForBuilding, this)(buildingID); + + /* not enough idle peasants for the workers: tell the local player */ + if (playerID == DAT_GameSynchronyState::instance.currentPlayerSlotID + && DAT_BuildingsState::instance.buildings[buildingID].buildingTypeBasedEmployeeCount + > DAT_GameState::instance.playerDataArray[playerID].availablePeasantsAtFire + && (DAT_GameState::instance.playerDataArray[playerID].populationCap + <= DAT_GameState::instance.playerDataArray[playerID].currentPopulation + || DAT_GameState::instance.playerDataArray[playerID].popularity < 5000)) { + MACRO_CALL_MEMBER(OpenSHC::UI::BottomLeftTextDisplayState_Func::setBottomLeftTextDisplayText, + DAT_BottomLeftTextDisplayState::ptr)(1, 0x4d, 1, 0, 100, 6000); + } + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/placeDefensiveStructureTile.cpp b/src/OpenSHC/Map/TileMapState/placeDefensiveStructureTile.cpp new file mode 100644 index 0000000000..08bbab2965 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/placeDefensiveStructureTile.cpp @@ -0,0 +1,121 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Map/Buildings/BuildingsState.func.hpp" +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" +#include "OpenSHC/UI/MinimapViewState.func.hpp" +#include "OpenSHC/Commands/MappersEnum.hpp" +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_LandscapeState.hpp" +#include "OpenSHC/Globals/DAT_MinimapViewState.hpp" +#include "OpenSHC/Globals/DAT_PathFindingState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_BOULDERS; + using OpenSHC::Map::LogicHelpers::L_CRENEL; + using OpenSHC::Map::LogicHelpers::L_CRENEL_VARIATIONUnk; + using OpenSHC::Map::LogicHelpers::L_IRON; + using OpenSHC::Map::LogicHelpers::L_PEBBLES; + using OpenSHC::Map::LogicHelpers::L_PLAIN2_AND_PITCH; + using OpenSHC::Map::LogicHelpers::L_STAIRS; + using OpenSHC::Map::LogicHelpers::L_TREE; + using OpenSHC::Map::LogicHelpers::L_UNKNOWN_WALL_RELATED; + using OpenSHC::Map::LogicHelpers::L_WALL_OR_GATEHOUSE; + + using OpenSHC::Map::LogicHelpers::L_BOULDERS; + using OpenSHC::Map::LogicHelpers::L_CRENEL; + using OpenSHC::Map::LogicHelpers::L_CRENEL_VARIATIONUnk; + using OpenSHC::Map::LogicHelpers::L_IRON; + using OpenSHC::Map::LogicHelpers::L_PEBBLES; + using OpenSHC::Map::LogicHelpers::L_PLAIN2_AND_PITCH; + using OpenSHC::Map::LogicHelpers::L_STAIRS; + using OpenSHC::Map::LogicHelpers::L_TREE; + using OpenSHC::Map::LogicHelpers::L_UNKNOWN_WALL_RELATED; + using OpenSHC::Map::LogicHelpers::L_WALL_OR_GATEHOUSE; + + using OpenSHC::Commands::MappersEnum; + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x005034A0 + void TileMapState::placeDefensiveStructureTile(int playerID, uint x, uint y, MappersEnum mapper) + { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::validateWallPlacementAtTile, this)(playerID, x, y, mapper); + if (this->illegalBuild != FALSE) { + return; + } + + int tile = DAT_ViewportRenderState::instance.translationMatrix[y].addXgetTile + x; + short command = (short)mapper; + this->DamageLayer[tile] = 0; + this->HeightLayer[tile] = this->DefaultHeightLayer[tile]; + if (command == OpenSHC::Commands::M_MAPPER_WALL) { + this->HeightLayer[tile] = this->DefaultHeightLayer[tile] + 0x5a; + } else if (command == OpenSHC::Commands::M_MAPPER_WOODWALL) { + this->HeightLayer[tile] = this->DefaultHeightLayer[tile] + 0x3c; + } else { + bool crenellated = true; + if (command == OpenSHC::Commands::M_MAPPER_CRENAL) { + this->LogicLayer[tile] = this->LogicLayer[tile] | L_CRENEL; + this->HeightLayer[tile] = this->HeightLayer[tile] + 0x62; + } else if (command == OpenSHC::Commands::M_MAPPER_CRENAL2) { + this->LogicLayer[tile] = this->LogicLayer[tile] | L_CRENEL; + this->HeightLayer[tile] = this->HeightLayer[tile] + 0x44; + } else { + crenellated = false; + if (command == OpenSHC::Commands::M_MAPPER_STAIR1) { + this->LogicLayer[tile] = this->LogicLayer[tile] | L_STAIRS; + this->HeightLayer[tile] = this->HeightLayer[tile] + 0x50; + } else if (command == OpenSHC::Commands::M_MAPPER_STAIR2) { + this->LogicLayer[tile] = this->LogicLayer[tile] | L_STAIRS; + this->HeightLayer[tile] = this->HeightLayer[tile] + 0x40; + } else if (command == OpenSHC::Commands::M_MAPPER_STAIR3) { + this->LogicLayer[tile] = this->LogicLayer[tile] | L_STAIRS; + this->HeightLayer[tile] = this->HeightLayer[tile] + 0x30; + } else if (command == OpenSHC::Commands::M_MAPPER_STAIR4) { + this->LogicLayer[tile] = this->LogicLayer[tile] | L_STAIRS; + this->HeightLayer[tile] = this->HeightLayer[tile] + 0x20; + } + } + /* a crenel on an odd tile of one axis carries the alternate variation */ + if (crenellated && ((x & 1) == 0) != ((y & 1) == 0)) { + this->LogicLayer[tile] = this->LogicLayer[tile] | L_CRENEL_VARIATIONUnk; + } + } + + uint logic = this->LogicLayer[tile]; + this->LogicLayer[tile] + = logic & ~(L_UNKNOWN_WALL_RELATED | L_BOULDERS | L_PEBBLES | L_IRON) | L_WALL_OR_GATEHOUSE; + if ((logic & L_PLAIN2_AND_PITCH) != 0) { + this->LogicLayer[tile] + = logic & ~(L_PLAIN2_AND_PITCH | L_UNKNOWN_WALL_RELATED | L_BOULDERS | L_PEBBLES | L_IRON) + | L_WALL_OR_GATEHOUSE; + this->HeightLayer[tile] = this->HeightLayer[tile] + 4; + } + if ((this->LogicLayer[tile] & L_TREE) != 0 && this->OrganismLayer[tile] < 2000) { + DAT_LandscapeState::instance.trees[this->OrganismLayer[tile]].state = 3; + } + if (command == OpenSHC::Commands::M_MAPPER_WOODWALL) { + this->LogicLayer[tile] = this->LogicLayer[tile] | L_UNKNOWN_WALL_RELATED; + } + this->WallOwnerLayer[tile] = this->WallOwnerLayer[tile] & 0xf8 | (char)playerID - 1U; + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::updatePathLinkagesInAllEightDirections, + DAT_PathFindingState::ptr)(y, tile); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::clearMoat, this)(tile); + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::updateWalkAndPathLayer, + DAT_PathFindingState::ptr)(7, x, y); + if (command != OpenSHC::Commands::M_MAPPER_STAIR1 && command != OpenSHC::Commands::M_MAPPER_STAIR2 + && command != OpenSHC::Commands::M_MAPPER_STAIR3 && command != OpenSHC::Commands::M_MAPPER_STAIR4 + && command != OpenSHC::Commands::M_MAPPER_STAIR5 && command != OpenSHC::Commands::M_MAPPER_STAIR6) { + MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::processWallBuildingLoss, + DAT_BuildingsState::ptr)(playerID, 1, 0, 0); + } + DAT_PathFindingState::instance.toggleUpdateSeparateAreaTileMap = 1; + MACRO_CALL_MEMBER(OpenSHC::UI::MinimapViewState_Func::triggerMinimapRedraw, DAT_MinimapViewState::ptr)(1); + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/placeDrawbridge.cpp b/src/OpenSHC/Map/TileMapState/placeDrawbridge.cpp new file mode 100644 index 0000000000..63bd95561e --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/placeDrawbridge.cpp @@ -0,0 +1,56 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Map/Buildings/BuildingsState.func.hpp" +#include "OpenSHC/Map/LogicHelpers/Logic1.hpp" +#include "OpenSHC/Map/Buildings/BuildingType.hpp" + +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_BUILDING; + using OpenSHC::Map::LogicHelpers::L_MOAT; + using OpenSHC::Map::Buildings::BuildingType; + + // FUNCTION: STRONGHOLDCRUSADER 0x00514DE0 + void TileMapState::placeDrawbridge( + int playerID, uint x, uint y, undefined4 buildingType, uint total, int* orientation, undefined4 averageHeight) + { + int tileIndex = 0; + int buildingID = MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::setupBuildingData, DAT_BuildingsState::ptr)( + playerID, x, y, averageHeight, (BuildingType)(int)(short)buildingType, total, playerID, (int)orientation); + int rot = (int)orientation / 2; + this->placedBuildingID = buildingID; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)( + tileIndex, total); + int tileUnk = DAT_ViewportRenderState::instance.translationMatrix[this->buildingY + y].addXgetTile + + this->buildingX + x; + DAT_BuildingsState::instance.buildings[buildingID].tileRefs[tileIndex] = tileUnk; + this->BuildingLayer[tileUnk] = (short)buildingID; + this->BuildingWasLayer[tileUnk] = (uchar)buildingType; + this->ChangedLayer[tileUnk] = 2; + if (DAT_TerrainDefinedData::instance.DrawbridgeTileMoatProperty[tileIndex] != 0) { + this->LogicLayer[tileUnk] = this->LogicLayer[tileUnk] | L_BUILDING; + } + if (DAT_TerrainDefinedData::instance.DrawbridgeOrientationMapping[rot][tileIndex] != 0) { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::createMoatData, this)( + playerID, this->buildingX + x, this->buildingY + y, 1); + this->LogicLayer[tileUnk] = this->LogicLayer[tileUnk] & ~L_MOAT; + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::setMoatVisualStateAtTile, this)(tileUnk, 0); + this->HeightLayer[tileUnk] = 0; + } else { + this->LogicLayer[tileUnk] = this->LogicLayer[tileUnk] & ~L_MOAT; + } + tileIndex++; + } while (tileIndex < this->constructionTileCount); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::setMiscDisplayLayer, this)(buildingID); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::updatePathLinkagesForBuilding, this)(buildingID); + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/placeEngineersguild.cpp b/src/OpenSHC/Map/TileMapState/placeEngineersguild.cpp new file mode 100644 index 0000000000..72a839b30b --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/placeEngineersguild.cpp @@ -0,0 +1,93 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Map/Buildings/BuildingsState.func.hpp" +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" +#include "OpenSHC/Map/Buildings/BuildingType.hpp" + +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_GameCore.hpp" +#include "OpenSHC/Globals/DAT_PathFindingState.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::Buildings::BuildingType; + + // FUNCTION: STRONGHOLDCRUSADER 0x00507BD0 + void TileMapState::placeEngineersguild( + int param_1, int* param_2, uint param_3, undefined4 param_4, uint param_5, int param_6, undefined4 param_7) + { + int* piVar1; + int iVar2; + int buildingID; + int iVar3; + uint y; + uint x; + int iVar4; + int iVar5; + int local_8; + piVar1 = param_2; + iVar5 = DAT_GameCore::instance.uniqueGameObjectTracker; + iVar4 = 0; + if (param_6 == 0xf) { + local_8 = 0; + } else { + local_8 = param_6 / 2; + } + iVar2 = MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::setupBuildingData, + DAT_BuildingsState::ptr)(param_1, (uint)(param_2), param_3, (undefined4)((int)(param_7)), + (BuildingType)((int)((short)param_4)), param_5, param_1, 0xf); + buildingID = (int)(short)iVar2; + this->placedBuildingID = buildingID; + DAT_BuildingsState::instance.buildings[buildingID].uidWhenPlaced = iVar5; + param_2 = &DAT_BuildingsState::instance.buildings[buildingID].tileRefs[0]; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)( + iVar4, (int)(param_5)); + iVar3 = DAT_ViewportRenderState::instance.translationMatrix[this->buildingY + param_3].addXgetTile + + this->buildingX + (int)piVar1; + *param_2 = iVar3; + this->HeightLayer[iVar3] = (byte)param_7; + this->LogicLayer[iVar3] = this->LogicLayer[iVar3] | 1024; + this->BuildingLayer[iVar3] = (short)iVar2; + iVar4 = iVar4 + 1; + param_2 = param_2 + 1; + this->BuildingWasLayer[iVar3] = (uchar)param_4; + this->ChangedLayer[iVar3] = 2; + } while (iVar4 < this->constructionTileCount); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::setMiscDisplayLayer, this)(buildingID); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::updatePathLinkagesForBuilding, this)(buildingID); + x = (int)piVar1 + DAT_TerrainDefinedData::instance.BuildingPartsOffsets[local_8][1].x; + y = param_3 + DAT_TerrainDefinedData::instance.BuildingPartsOffsets[local_8][1].y; + iVar4 = MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::setupBuildingData, DAT_BuildingsState::ptr)( + param_1, x, y, (undefined4)((int)(param_7)), OpenSHC::Map::Buildings::BT_PARADEGROUND, 5, param_1, 0xf); + iVar2 = (int)(short)iVar4; + DAT_BuildingsState::instance.buildings[iVar2].uidWhenPlaced = iVar5; + DAT_BuildingsState::instance.buildings[iVar2].quarryStockpileID = (undefined2)this->placedBuildingID; + param_5 = 0; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)( + param_5, (int)(DAT_BuildingsState::instance.buildings[iVar2].widthOrHeight)); + iVar5 = DAT_ViewportRenderState::instance.translationMatrix[this->buildingY + y].addXgetTile + + this->buildingX + x; + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::resetTileAndClearMoat, this)(iVar5); + this->HeightLayer[iVar5] = (byte)param_7; + this->BuildingLayer[iVar5] = (short)iVar4; + param_5 = param_5 + 1; + this->BuildingWasLayer[iVar5] = (uchar)param_4; + this->ChangedLayer[iVar5] = 2; + } while ((int)param_5 < this->constructionTileCount); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::setMiscDisplayLayer, this)(iVar2); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::updatePathLinkagesForBuilding, this)(iVar2); + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::updateWalkAndPathLayer, + DAT_PathFindingState::ptr)(8, x, y); + MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::setupEngineersGuildParagroundPositions, + DAT_BuildingsState::ptr)(param_1); + return; + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/placeGatehouseLarge.cpp b/src/OpenSHC/Map/TileMapState/placeGatehouseLarge.cpp new file mode 100644 index 0000000000..bfaa2a2310 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/placeGatehouseLarge.cpp @@ -0,0 +1,57 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Map/Buildings/BuildingsState.func.hpp" +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" + +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_GameCore.hpp" +#include "OpenSHC/Globals/DAT_PathFindingState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_WALL_OR_GATEHOUSE; + + // FUNCTION: STRONGHOLDCRUSADER 0x00507560 + void TileMapState::placeGatehouseLarge( + int param_1, uint param_2, uint param_3, undefined4 param_4, uint param_5, int param_6, undefined4 param_7) + { + int uniqueID = DAT_GameCore::instance.uniqueGameObjectTracker; + int buildingSizeTileIndex = 0; + int buildingID = MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::setupBuildingData, DAT_BuildingsState::ptr)( + param_1, param_2, param_3, param_7, (BuildingType)(short)param_4, param_5, param_1, param_6); + this->placedBuildingID = buildingID; + DAT_BuildingsState::instance.buildings[buildingID].uidWhenPlaced = uniqueID; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)( + buildingSizeTileIndex, param_5); + int tileUnk = DAT_ViewportRenderState::instance.translationMatrix[this->buildingY + param_3].addXgetTile + + param_2 + this->buildingX; + if (buildingSizeTileIndex < 36) { + DAT_BuildingsState::instance.buildings[buildingID].tileRefs[buildingSizeTileIndex] = tileUnk; + } + this->HeightLayer[tileUnk] = (char)param_7 + 0x5a; + this->LogicLayer[tileUnk] = this->LogicLayer[tileUnk] | L_WALL_OR_GATEHOUSE; + this->WallOwnerLayer[tileUnk] = this->WallOwnerLayer[tileUnk] & 0xf8 | (char)param_1 - 1U; + this->MiscDisplayLayer[tileUnk] = this->MiscDisplayLayer[tileUnk] | 0x20; + this->BuildingLayer[tileUnk] = (short)buildingID; + buildingSizeTileIndex++; + this->BuildingWasLayer[tileUnk] = (uchar)param_4; + this->ChangedLayer[tileUnk] = 2; + } while (buildingSizeTileIndex < this->constructionTileCount); + + if (param_6 == 0x50) { + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::createClimbData, DAT_PathFindingState::ptr)( + 3, buildingID, 0, 2, 0); + } else { + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::createClimbData, DAT_PathFindingState::ptr)( + 3, buildingID, 0, 0, 0); + } + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::setMiscDisplayLayer, this)(buildingID); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::updatePathLinkagesForBuilding, this)(buildingID); + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/placeGatehouseSmall.cpp b/src/OpenSHC/Map/TileMapState/placeGatehouseSmall.cpp new file mode 100644 index 0000000000..c12033dd50 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/placeGatehouseSmall.cpp @@ -0,0 +1,57 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Map/Buildings/BuildingsState.func.hpp" +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" + +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_GameCore.hpp" +#include "OpenSHC/Globals/DAT_PathFindingState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_WALL_OR_GATEHOUSE; + + // FUNCTION: STRONGHOLDCRUSADER 0x00507420 + void TileMapState::placeGatehouseSmall( + int param_1, uint param_2, uint param_3, undefined4 param_4, uint param_5, int param_6, undefined4 param_7) + { + int uniqueID = DAT_GameCore::instance.uniqueGameObjectTracker; + int buildingSizeTileIndex = 0; + int buildingID = MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::setupBuildingData, DAT_BuildingsState::ptr)( + param_1, param_2, param_3, param_7, (BuildingType)(short)param_4, param_5, param_1, param_6); + this->placedBuildingID = buildingID; + DAT_BuildingsState::instance.buildings[buildingID].uidWhenPlaced = uniqueID; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)( + buildingSizeTileIndex, param_5); + int tileUnk = DAT_ViewportRenderState::instance.translationMatrix[this->buildingY + param_3].addXgetTile + + param_2 + this->buildingX; + if (buildingSizeTileIndex < 36) { + DAT_BuildingsState::instance.buildings[buildingID].tileRefs[buildingSizeTileIndex] = tileUnk; + } + this->HeightLayer[tileUnk] = (char)param_7 + 0x5a; + this->LogicLayer[tileUnk] = this->LogicLayer[tileUnk] | L_WALL_OR_GATEHOUSE; + this->WallOwnerLayer[tileUnk] = this->WallOwnerLayer[tileUnk] & 0xf8 | (char)param_1 - 1U; + this->MiscDisplayLayer[tileUnk] = this->MiscDisplayLayer[tileUnk] | 0x20; + this->BuildingLayer[tileUnk] = (short)buildingID; + buildingSizeTileIndex++; + this->BuildingWasLayer[tileUnk] = (uchar)param_4; + this->ChangedLayer[tileUnk] = 2; + } while (buildingSizeTileIndex < this->constructionTileCount); + + if (param_6 == 0x50) { + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::createClimbData, DAT_PathFindingState::ptr)( + 4, buildingID, 0, 2, 0); + } else { + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::createClimbData, DAT_PathFindingState::ptr)( + 4, buildingID, 0, 0, 0); + } + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::setMiscDisplayLayer, this)(buildingID); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::updatePathLinkagesForBuilding, this)(buildingID); + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/placeHopfarm.cpp b/src/OpenSHC/Map/TileMapState/placeHopfarm.cpp new file mode 100644 index 0000000000..467f0ecb72 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/placeHopfarm.cpp @@ -0,0 +1,123 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Map/Buildings/BuildingsState.func.hpp" +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" +#include "OpenSHC/UI/BottomLeftTextDisplayState.func.hpp" +#include "OpenSHC/Map/LogicHelpers/Logic1.hpp" +#include "OpenSHC/Map/LogicHelpers/Logic2.hpp" + +#include "OpenSHC/Globals/DAT_BottomLeftTextDisplayState.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_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::Logic1; + using OpenSHC::Map::LogicHelpers::Logic2; + + // FUNCTION: STRONGHOLDCRUSADER 0x005151C0 + void TileMapState::placeHopfarm( + int param_1, uint param_2, uint param_3, undefined4 param_4, undefined4 param_5, int param_6, int param_7) + { + undefined1* puVar1; + uint uVar2; + int buildingID; + XYPair* pXVar3; + int iVar4; + int* piVar5; + int buildingSizeTileIndex; + uVar2 = param_2; + buildingSizeTileIndex = 0; + buildingID = MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::setupBuildingData, DAT_BuildingsState::ptr)(param_1, param_2, + param_3, (undefined4)((int)(param_7)), (BuildingType)((int)((short)param_4)), 3, param_1, param_6); + this->placedBuildingID = buildingID; + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::markBuildingFootprintFlag, this)(param_2, (int)(param_3), 9); + iVar4 = *(int*)&DAT_GameState::instance.playerDataArray[param_1].unkHopFarmVariation; + param_2 = 4; + pXVar3 = DAT_TerrainDefinedData::instance.HopFarmProperty1[iVar4]; + piVar5 = &DAT_BuildingsState::instance.buildings[buildingID].tileRefs[1]; + do { + piVar5[-1] = DAT_ViewportRenderState::instance.translationMatrix[pXVar3->y + param_3].addXgetTile + + ((XYPair*)&pXVar3->x)->x + uVar2; + *piVar5 = DAT_ViewportRenderState::instance.translationMatrix[pXVar3[1].y + param_3].addXgetTile + + pXVar3[1].x + uVar2; + piVar5[1] = DAT_ViewportRenderState::instance.translationMatrix[pXVar3[2].y + param_3].addXgetTile + + pXVar3[2].x + uVar2; + piVar5[2] = DAT_ViewportRenderState::instance.translationMatrix[pXVar3[3].y + param_3].addXgetTile + + pXVar3[3].x + uVar2; + piVar5[3] = DAT_ViewportRenderState::instance.translationMatrix[pXVar3[4].y + param_3].addXgetTile + + pXVar3[4].x + uVar2; + param_2 = param_2 - 1; + piVar5[4] = DAT_ViewportRenderState::instance.translationMatrix[pXVar3[5].y + param_3].addXgetTile + + pXVar3[5].x + uVar2; + pXVar3 = pXVar3 + 6; + piVar5 = piVar5 + 6; + } while (param_2 != 0); + *(ushort*)&DAT_BuildingsState::instance.buildings[buildingID].padding_0x26e + = (-(ushort)(iVar4 != 0) & 0xffb6) + 0x51; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)( + buildingSizeTileIndex, 3); + *(short*)¶m_6 = (short)buildingID; + iVar4 = DAT_ViewportRenderState::instance.translationMatrix[this->buildingY + param_3].addXgetTile + + this->buildingX + uVar2; + this->HeightLayer[iVar4] = (byte)param_7; + this->LogicLayer[iVar4] = this->LogicLayer[iVar4] | 1024; + this->BuildingLayer[iVar4] = (short)param_6; + this->BuildingWasLayer[iVar4] = (uchar)param_4; + this->ChangedLayer[iVar4] = 2; + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::setTerrain, this)(param_1, iVar4, + this->buildingY + param_3, 2, OpenSHC::Map::LogicHelpers::L_NONE, + OpenSHC::Map::LogicHelpers::L2_THICK_SCRUB); + buildingSizeTileIndex = buildingSizeTileIndex + 1; + } while (buildingSizeTileIndex < this->constructionTileCount); + param_7 = 0; + do { + iVar4 = *(int*)&DAT_GameState::instance.playerDataArray[param_1].unkHopFarmVariation; + iVar4 + = DAT_ViewportRenderState::instance + .translationMatrix[DAT_TerrainDefinedData::instance.HopFarmProperty1[iVar4][param_7].y + param_3] + .addXgetTile + + DAT_TerrainDefinedData::instance.HopFarmProperty1[iVar4][param_7].x + uVar2; + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::resetTileAndClearMoat, this)(iVar4); + this->LogicLayer[iVar4] = this->LogicLayer[iVar4] | 33554432; + this->BuildingLayer[iVar4] = (short)param_6; + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::updatePathLinkagesInAllEightDirections, + DAT_PathFindingState::ptr)( + DAT_TerrainDefinedData::instance + .HopFarmProperty1[*(int*)&DAT_GameState::instance.playerDataArray[param_1].unkHopFarmVariation] + [param_7] + .y + + param_3, + iVar4); + param_7 = param_7 + 1; + this->BuildingWasLayer[iVar4] = (uchar)param_4; + this->ChangedLayer[iVar4] = 2; + } while (param_7 < 0x18); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::setMiscDisplayLayer, this)(buildingID); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::updatePathLinkagesForBuilding, this)(buildingID); + puVar1 = &DAT_GameState::instance.playerDataArray[param_1].unkHopFarmVariation; + *(int*)puVar1 = *(int*)puVar1 + 1; + if (1 < *(int*)&DAT_GameState::instance.playerDataArray[param_1].unkHopFarmVariation) { + *(undefined4*)&DAT_GameState::instance.playerDataArray[param_1].unkHopFarmVariation = 0; + } + if (param_1 == DAT_GameSynchronyState::instance.currentPlayerSlotID + && DAT_GameState::instance.playerDataArray[param_1].availablePeasantsAtFire + < (int)DAT_BuildingsState::instance.buildings[buildingID].buildingTypeBasedEmployeeCount + && (DAT_GameState::instance.playerDataArray[param_1].populationCap + <= DAT_GameState::instance.playerDataArray[param_1].currentPopulation + || (DAT_GameState::instance.playerDataArray[param_1].popularity < 5000))) { + MACRO_CALL_MEMBER(OpenSHC::UI::BottomLeftTextDisplayState_Func::setBottomLeftTextDisplayText, + DAT_BottomLeftTextDisplayState::ptr)(1, 0x4d, 1, 0, 100, 6000); + } + return; + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/placeKeep.cpp b/src/OpenSHC/Map/TileMapState/placeKeep.cpp new file mode 100644 index 0000000000..4e0d3b4345 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/placeKeep.cpp @@ -0,0 +1,241 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Game/GameStateStructures.func.hpp" +#include "OpenSHC/Map/Buildings/BuildingsState.func.hpp" +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" +#include "OpenSHC/Game/Player/PlayerDataBuildingCategoryEnum.hpp" +#include "OpenSHC/Map/Buildings/BuildingType.hpp" +#include "OpenSHC/Map/LogicHelpers/Logic1.hpp" +#include "OpenSHC/Map/LogicHelpers/Logic2.hpp" + +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_GameCore.hpp" +#include "OpenSHC/Globals/DAT_GameState.hpp" +#include "OpenSHC/Globals/DAT_PathFindingState.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_BUILDING; + using OpenSHC::Map::LogicHelpers::L_KEEP_NON_MANOR_HOUSE; + + using OpenSHC::Game::Player::PlayerDataBuildingCategoryEnum; + using OpenSHC::Map::Buildings::BuildingType; + using OpenSHC::Map::LogicHelpers::Logic1; + using OpenSHC::Map::LogicHelpers::Logic2; + + // FUNCTION: STRONGHOLDCRUSADER 0x005146D0 + void TileMapState::placeKeep( + int playerID, uint x, uint y, BuildingType type, uint size, int orientation, int xyValue) + { + uint baseX = x; + uint baseY = y; + if (this->clearKeepFootprintOnPlace != 0) { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::demolishBuildingsInKeepsConstructionFootprint, this)( + playerID, x, y, type, size, orientation, xyValue); + this->clearKeepFootprintOnPlace = 0; + } + + int uid = DAT_GameCore::instance.uniqueGameObjectTracker; + int keepKind = 0; + byte logic2 = this->Logic2Layer[DAT_ViewportRenderState::instance.translationMatrix[baseY].addXgetTile + baseX]; + int keepID = MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::setupBuildingData, + DAT_BuildingsState::ptr)(playerID, baseX, baseY, xyValue, (BuildingType)(short)type, size, playerID, 0xf); + this->placedBuildingID = keepID; + DAT_BuildingsState::instance.buildings[keepID].uidWhenPlaced = uid; + short keepOrientation = (short)orientation; + DAT_BuildingsState::instance.buildings[keepID].orientation = keepOrientation; + MACRO_CALL_MEMBER( + OpenSHC::Game::GameStateStructures_Func::computeBuildingCategoryEntryPointAndDestroyEarlierBuilding, + DAT_GameState::ptr)(keepID, playerID, OpenSHC::Game::Player::PDBCE_KEEP); + if (orientation == 0xf) { + orientation = 0; + } + + int index = 0; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)(index, size); + int tile = DAT_ViewportRenderState::instance.translationMatrix[this->buildingY + baseY].addXgetTile + + this->buildingX + baseX; + if (index < 0x24) { + DAT_BuildingsState::instance.buildings[keepID].tileRefs[index] = tile; + } + this->HeightLayer[tile] = (byte)xyValue; + if ((short)type == OpenSHC::Map::Buildings::BT_MANORHOUSE) { + this->LogicLayer[tile] = this->LogicLayer[tile] | L_BUILDING; + } else { + this->LogicLayer[tile] = this->LogicLayer[tile] | L_KEEP_NON_MANOR_HOUSE; + } + this->BuildingLayer[tile] = (short)keepID; + this->BuildingWasLayer[tile] = (uchar)type; + /* grass and scrub come back as scrub, anything else as bare earth */ + Logic2 terrain; + uint brush; + if ((logic2 & (OpenSHC::Map::LogicHelpers::L2_OASIS_GRASS | OpenSHC::Map::LogicHelpers::L2_THICK_SCRUB)) + == 0) { + terrain = OpenSHC::Map::LogicHelpers::L2_EARTH_AND_STONES; + brush = 6; + } else { + terrain = OpenSHC::Map::LogicHelpers::L2_THICK_SCRUB; + brush = 3; + } + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::setTerrain, this)( + playerID, tile, this->buildingY + baseY, brush, OpenSHC::Map::LogicHelpers::L_NONE, terrain); + this->ChangedLayer[tile] = 2; + index++; + } while (index < this->constructionTileCount); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::setMiscDisplayLayer, this)(keepID); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::updatePathLinkagesForBuilding, this)(keepID); + if ((short)type == OpenSHC::Map::Buildings::BT_MANORHOUSE + || (short)type == OpenSHC::Map::Buildings::BT_STONEKEEP) { + keepKind = 2; + } + + /* the three keep doors and the two outbuildings are laid out per keep type and orientation */ + int group = orientation / 2 + -0xa0 + (short)type * 4; + { + int doorX = DAT_TerrainDefinedData::instance.field130_0x264[0][group * 3 + 0].x + baseX; + uint doorY = DAT_TerrainDefinedData::instance.field130_0x264[0][group * 3 + 0].y + baseY; + int doorTile = DAT_ViewportRenderState::instance.translationMatrix[doorY].addXgetTile + doorX; + int doorID = MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::setupBuildingData, DAT_BuildingsState::ptr)( + playerID, doorX, doorY, xyValue, OpenSHC::Map::Buildings::BT_KEEPDOOR_LEFT, 1, playerID, 0xf); + DAT_BuildingsState::instance.buildings[doorID].uidWhenPlaced = uid; + DAT_BuildingsState::instance.buildings[doorID].unknownManorHouseOrStoneKeepRelated = keepKind; + DAT_BuildingsState::instance.buildings[doorID].quarryStockpileID = (short)this->placedBuildingID; + DAT_BuildingsState::instance.buildings[doorID].orientation = keepOrientation; + this->LogicLayer[doorTile] = this->LogicLayer[doorTile] | L_BUILDING; + this->BuildingLayer[doorTile] = (short)doorID; + this->ChangedLayer[doorTile] = 2; + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::updatePathLinkagesInAllEightDirections, + DAT_PathFindingState::ptr)((short)DAT_BuildingsState::instance.buildings[doorID].y, doorTile); + } + + { + int doorX = DAT_TerrainDefinedData::instance.field130_0x264[0][group * 3 + 1].x + baseX; + uint doorY = DAT_TerrainDefinedData::instance.field130_0x264[0][group * 3 + 1].y + baseY; + int doorTile = DAT_ViewportRenderState::instance.translationMatrix[doorY].addXgetTile + doorX; + int doorID = MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::setupBuildingData, DAT_BuildingsState::ptr)( + playerID, doorX, doorY, xyValue, OpenSHC::Map::Buildings::BT_KEEPDOOR, 1, playerID, 0xf); + DAT_BuildingsState::instance.buildings[doorID].uidWhenPlaced = uid; + DAT_BuildingsState::instance.buildings[doorID].unknownManorHouseOrStoneKeepRelated = keepKind / 2; + DAT_BuildingsState::instance.buildings[doorID].quarryStockpileID = (short)this->placedBuildingID; + DAT_BuildingsState::instance.buildings[doorID].orientation = keepOrientation; + this->MiscDisplayLayer[doorTile] = this->MiscDisplayLayer[doorTile] | 4; + this->BuildingLayer[doorTile] = (short)doorID; + this->ChangedLayer[doorTile] = 2; + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::updatePathLinkagesInAllEightDirections, + DAT_PathFindingState::ptr)((short)DAT_BuildingsState::instance.buildings[doorID].y, doorTile); + } + + { + int doorX = DAT_TerrainDefinedData::instance.field130_0x264[0][group * 3 + 2].x + baseX; + uint doorY = DAT_TerrainDefinedData::instance.field130_0x264[0][group * 3 + 2].y + baseY; + int doorTile = DAT_ViewportRenderState::instance.translationMatrix[doorY].addXgetTile + doorX; + int doorID = MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::setupBuildingData, DAT_BuildingsState::ptr)( + playerID, doorX, doorY, xyValue, OpenSHC::Map::Buildings::BT_KEEPDOOR_RIGHT, 1, playerID, 0xf); + DAT_BuildingsState::instance.buildings[doorID].uidWhenPlaced = uid; + DAT_BuildingsState::instance.buildings[doorID].unknownManorHouseOrStoneKeepRelated = keepKind; + DAT_BuildingsState::instance.buildings[doorID].quarryStockpileID = (short)this->placedBuildingID; + DAT_BuildingsState::instance.buildings[doorID].orientation = keepOrientation; + this->LogicLayer[doorTile] = this->LogicLayer[doorTile] | L_BUILDING; + this->BuildingLayer[doorTile] = (short)doorID; + this->ChangedLayer[doorTile] = 2; + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::updatePathLinkagesInAllEightDirections, + DAT_PathFindingState::ptr)((short)DAT_BuildingsState::instance.buildings[doorID].y, doorTile); + } + + uint campX = baseX + DAT_TerrainDefinedData::instance.keepOutbuildingOffsets_0x384[0][group].xOffset; + uint campY = baseY + DAT_TerrainDefinedData::instance.keepOutbuildingOffsets_0x384[0][group].yOffset; + int campID = MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::setupBuildingData, DAT_BuildingsState::ptr)( + playerID, campX, campY, xyValue, OpenSHC::Map::Buildings::BT_CAMPGROUND, 7, playerID, 0xf); + DAT_BuildingsState::instance.buildings[campID].uidWhenPlaced = uid; + DAT_BuildingsState::instance.buildings[campID].quarryStockpileID = (short)this->placedBuildingID; + DAT_BuildingsState::instance.buildings[campID].orientation = keepOrientation; + MACRO_CALL_MEMBER( + OpenSHC::Game::GameStateStructures_Func::computeBuildingCategoryEntryPointAndDestroyEarlierBuilding, + DAT_GameState::ptr)(campID, playerID, OpenSHC::Game::Player::PDBCE_CAMPGROUND); + + index = 0; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)(index, 7); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::resetTileAndClearMoat, this)( + DAT_ViewportRenderState::instance.translationMatrix[this->buildingY + campY].addXgetTile + + this->buildingX + campX); + index++; + } while (index < this->constructionTileCount); + + index = 0; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)( + index, DAT_BuildingsState::instance.buildings[campID].widthOrHeight); + int tile = DAT_ViewportRenderState::instance.translationMatrix[this->buildingY + campY].addXgetTile + + this->buildingX + campX; + if (index < 0x18) { + DAT_BuildingsState::instance.buildings[campID].tileRefs[index] + = DAT_ViewportRenderState::instance + .translationMatrix[(short)DAT_BuildingsState::instance.buildings[campID].y + + DAT_TerrainDefinedData::instance.field197_0x444[index].y] + .addXgetTile + + (short)DAT_BuildingsState::instance.buildings[campID].x + + DAT_TerrainDefinedData::instance.field197_0x444[index].x; + } + this->HeightLayer[tile] = (byte)xyValue; + /* only the campground's cross of five middle tiles blocks movement */ + if (this->buildingX == 3 && this->buildingY == 3) { + this->LogicLayer[tile] = this->LogicLayer[tile] | L_BUILDING; + } + if (this->buildingX == 3 && this->buildingY == 2) { + this->LogicLayer[tile] = this->LogicLayer[tile] | L_BUILDING; + } + if (this->buildingX == 3 && this->buildingY == 4) { + this->LogicLayer[tile] = this->LogicLayer[tile] | L_BUILDING; + } + if (this->buildingX == 2 && this->buildingY == 3) { + this->LogicLayer[tile] = this->LogicLayer[tile] | L_BUILDING; + } + if (this->buildingX == 4 && this->buildingY == 3) { + this->LogicLayer[tile] = this->LogicLayer[tile] | L_BUILDING; + } + this->BuildingLayer[tile] = (short)campID; + this->ChangedLayer[tile] = 2; + Logic2 terrain; + uint brush; + if ((logic2 & (OpenSHC::Map::LogicHelpers::L2_OASIS_GRASS | OpenSHC::Map::LogicHelpers::L2_THICK_SCRUB)) + == 0) { + terrain = OpenSHC::Map::LogicHelpers::L2_EARTH_AND_STONES; + brush = 6; + } else { + terrain = OpenSHC::Map::LogicHelpers::L2_THICK_SCRUB; + brush = 3; + } + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::setTerrain, this)( + playerID, tile, this->buildingY + campY, brush, OpenSHC::Map::LogicHelpers::L_NONE, terrain); + index++; + } while (index < this->constructionTileCount); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::setMiscDisplayLayer, this)(campID); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::updatePathLinkagesForBuilding, this)(campID); + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::updateWalkAndPathLayer, + DAT_PathFindingState::ptr)(10, campX, campY); + + int stockpileX = DAT_TerrainDefinedData::instance.keepOutbuildingOffsets_0x3e4[0][group].xOffset; + int stockpileY = DAT_TerrainDefinedData::instance.keepOutbuildingOffsets_0x3e4[0][group].yOffset; + index = 0; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)(index, 5); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::resetTileAndClearMoat, this)( + DAT_ViewportRenderState::instance.translationMatrix[this->buildingY + stockpileY + baseY].addXgetTile + + this->buildingX + stockpileX + baseX); + index++; + } while (index < this->constructionTileCount); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::placeStockpile, this)( + playerID, stockpileX + baseX, stockpileY + baseY, 10, 5, 0xf, xyValue); + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/placeKillingPit.cpp b/src/OpenSHC/Map/TileMapState/placeKillingPit.cpp new file mode 100644 index 0000000000..4e74e01cad --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/placeKillingPit.cpp @@ -0,0 +1,78 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Map/Buildings/BuildingsState.func.hpp" +#include "OpenSHC/UI/BottomLeftTextDisplayState.func.hpp" +#include "OpenSHC/Map/LogicHelpers/Logic1.hpp" +#include "OpenSHC/Map/LogicHelpers/Logic2.hpp" + +#include "OpenSHC/Globals/DAT_BottomLeftTextDisplayState.hpp" +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_GameState.hpp" +#include "OpenSHC/Globals/DAT_GameSynchronyState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::Logic1; + using OpenSHC::Map::LogicHelpers::Logic2; + + // FUNCTION: STRONGHOLDCRUSADER 0x00514520 + void TileMapState::placeKillingPit( + int playerID, uint x, uint y, undefined4 buildingType, uint sizeIndex, int buildingState, int height) + { + /* the original masks the terrain bits once, before the building is even created */ + int grassOrScrub = this->Logic2Layer[DAT_ViewportRenderState::instance.translationMatrix[y].addXgetTile + x] + & (OpenSHC::Map::LogicHelpers::L2_OASIS_GRASS | OpenSHC::Map::LogicHelpers::L2_THICK_SCRUB); + int index = 0; + int buildingID = MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::setupBuildingData, DAT_BuildingsState::ptr)( + playerID, x, y, height, (BuildingType)(int)(short)buildingType, sizeIndex, playerID, buildingState); + this->placedBuildingID = buildingID; + if ((short)buildingType != 0x43) { + height = height - 4; + if (height < 0) { + height = 0; + } + } + + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)(index, sizeIndex); + int tile = DAT_ViewportRenderState::instance.translationMatrix[this->buildingY + y].addXgetTile + + this->buildingX + x; + if (index < 0x24) { + DAT_BuildingsState::instance.buildings[buildingID].tileRefs[index] = tile; + } + this->HeightLayer[tile] = (byte)height; + this->BuildingLayer[tile] = (short)buildingID; + this->BuildingWasLayer[tile] = (uchar)(short)buildingType; + if ((short)buildingType != 0x43) { + /* bug:fixme: a pit dug in grass comes back as thick scrub, not as the terrain it replaced */ + Logic2 terrain; + if (grassOrScrub == 0) { + terrain = OpenSHC::Map::LogicHelpers::L2_EARTH_AND_STONES; + } else { + terrain = OpenSHC::Map::LogicHelpers::L2_THICK_SCRUB; + } + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::setTerrain, this)( + playerID, tile, this->buildingY + y, 3, OpenSHC::Map::LogicHelpers::L_NONE, terrain); + } + index++; + this->ChangedLayer[tile] = 2; + } while (index < this->constructionTileCount); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::setMiscDisplayLayer, this)(buildingID); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::updatePathLinkagesForBuilding, this)(buildingID); + + if (playerID == DAT_GameSynchronyState::instance.currentPlayerSlotID + && DAT_GameState::instance.playerDataArray[playerID].availablePeasantsAtFire + < DAT_BuildingsState::instance.buildings[buildingID].buildingTypeBasedEmployeeCount + && (DAT_GameState::instance.playerDataArray[playerID].populationCap + <= DAT_GameState::instance.playerDataArray[playerID].currentPopulation + || DAT_GameState::instance.playerDataArray[playerID].popularity < 5000)) { + MACRO_CALL_MEMBER(OpenSHC::UI::BottomLeftTextDisplayState_Func::setBottomLeftTextDisplayText, + DAT_BottomLeftTextDisplayState::ptr)(1, 0x4d, 1, 0, 100, 6000); + } + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/placeOilsmelter.cpp b/src/OpenSHC/Map/TileMapState/placeOilsmelter.cpp new file mode 100644 index 0000000000..a7836fdb15 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/placeOilsmelter.cpp @@ -0,0 +1,87 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Map/Buildings/BuildingsState.func.hpp" +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" +#include "OpenSHC/Map/Buildings/BuildingType.hpp" + +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_GameCore.hpp" +#include "OpenSHC/Globals/DAT_PathFindingState.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_BUILDING; + + using OpenSHC::Map::Buildings::BuildingType; + + // FUNCTION: STRONGHOLDCRUSADER 0x00508030 + void TileMapState::placeOilsmelter( + int playerID, uint x, uint y, undefined4 height, uint sizeIndex, int buildingTypeLike, undefined4 param_7) + { + int uid = DAT_GameCore::instance.uniqueGameObjectTracker; + + if (buildingTypeLike == 0xf) { + buildingTypeLike = 0; + } else { + buildingTypeLike = buildingTypeLike / 2; + } + + /* the id is kept zero-extended for the layer stores and sign-extended for the array index */ + ushort smelterID = MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::setupBuildingData, DAT_BuildingsState::ptr)( + playerID, x, y, param_7, (BuildingType)(int)(short)height, sizeIndex, playerID, 0xf); + int buildingID = (short)smelterID; + this->placedBuildingID = buildingID; + DAT_BuildingsState::instance.buildings[buildingID].uidWhenPlaced = uid; + + int index = 0; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)(index, sizeIndex); + int tile = DAT_ViewportRenderState::instance.translationMatrix[this->buildingY + y].addXgetTile + + this->buildingX + x; + this->HeightLayer[tile] = (byte)param_7; + this->LogicLayer[tile] = this->LogicLayer[tile] | L_BUILDING; + this->BuildingLayer[tile] = smelterID; + index++; + this->BuildingWasLayer[tile] = (uchar)height; + this->ChangedLayer[tile] = 2; + } while (index < this->constructionTileCount); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::setMiscDisplayLayer, this)(buildingID); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::updatePathLinkagesForBuilding, this)(buildingID); + + /* the campfire sits at a fixed offset from the smelter, chosen by the smelter's size */ + x = x + DAT_TerrainDefinedData::instance.field63_0x19c[buildingTypeLike].x; + y = y + DAT_TerrainDefinedData::instance.field63_0x19c[buildingTypeLike].y; + ushort campfire = MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::setupBuildingData, + DAT_BuildingsState::ptr)(playerID, x, y, param_7, OpenSHC::Map::Buildings::BT_CAMPFIRE, 4, playerID, 0xf); + int campfireID = (short)campfire; + DAT_BuildingsState::instance.buildings[campfireID].uidWhenPlaced = uid; + DAT_BuildingsState::instance.buildings[campfireID].quarryStockpileID = (short)this->placedBuildingID; + DAT_BuildingsState::instance.buildings[buildingID].quarryStockpileID = smelterID; + + index = 0; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)( + index, DAT_BuildingsState::instance.buildings[campfireID].widthOrHeight); + int tile = DAT_ViewportRenderState::instance.translationMatrix[this->buildingY + y].addXgetTile + + this->buildingX + x; + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::resetTileAndClearMoat, this)(tile); + this->HeightLayer[tile] = (byte)param_7; + this->BuildingLayer[tile] = campfire; + index++; + this->BuildingWasLayer[tile] = (uchar)height; + this->ChangedLayer[tile] = 2; + } while (index < this->constructionTileCount); + MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::setTileRefsForOilSmelter, + DAT_BuildingsState::ptr)(campfireID); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::setMiscDisplayLayer, this)(campfireID); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::updatePathLinkagesForBuilding, this)(campfireID); + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::updateWalkAndPathLayer, + DAT_PathFindingState::ptr)(8, x, y); + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/placePitchDitch.cpp b/src/OpenSHC/Map/TileMapState/placePitchDitch.cpp new file mode 100644 index 0000000000..ad931965b4 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/placePitchDitch.cpp @@ -0,0 +1,68 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Random/RNG.func.hpp" + +#include "OpenSHC/Globals/DAT_GameCore.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" +#include "OpenSHC/Globals/SEC_RNG.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_PLAIN2_AND_PITCH; + + // FUNCTION: STRONGHOLDCRUSADER 0x005116E0 + int TileMapState::placePitchDitch(undefined4 playerID, uint x, uint y) + { + if (x > 399 || y > 399) { + return 0; + } + if (DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[y * 400 + x] == 0) { + return 0; + } + + int existingPitchDitchID = MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getPitchDitchIDForTile, this)( + DAT_ViewportRenderState::instance.translationMatrix[y].addXgetTile + x); + if (existingPitchDitchID != 0) { + return existingPitchDitchID; + } + + for (int pitchDitchID = 1; pitchDitchID < 4000; pitchDitchID++) { + if (this->pitchDitches[pitchDitchID].owner != 0) { + continue; + } + + if (this->maxPitchDitchCount <= pitchDitchID) { + this->maxPitchDitchCount = pitchDitchID + 1; + } + this->pitchDitches[pitchDitchID].owner = (short)playerID; + this->pitchDitches[pitchDitchID].uid = DAT_GameCore::instance.uniqueGameObjectTracker; + DAT_GameCore::instance.uniqueGameObjectTracker = DAT_GameCore::instance.uniqueGameObjectTracker + 1; + this->pitchDitches[pitchDitchID].y = (short)y; + this->pitchDitches[pitchDitchID].x = (short)x; + this->pitchDitches[pitchDitchID].state = 0; + this->pitchDitches[pitchDitchID].field7_0x12 = 0; + this->pitchDitches[pitchDitchID].tile + = DAT_ViewportRenderState::instance.translationMatrix[y].addXgetTile + x; + this->pitchDitches[pitchDitchID].rng = SEC_RNG::instance.currentNumber2; + if (this->HeightLayer[this->pitchDitches[pitchDitchID].tile] < 5) { + this->HeightLayer[this->pitchDitches[pitchDitchID].tile] = 0; + } else { + this->HeightLayer[this->pitchDitches[pitchDitchID].tile] + = this->HeightLayer[this->pitchDitches[pitchDitchID].tile] - 4; + } + MACRO_CALL_MEMBER(OpenSHC::Random::RNG_Func::nextRandomNumber2, SEC_RNG::ptr)(); + this->LogicLayer[this->pitchDitches[pitchDitchID].tile] + = this->LogicLayer[this->pitchDitches[pitchDitchID].tile] | L_PLAIN2_AND_PITCH; + this->MiscDisplayLayer[this->pitchDitches[pitchDitchID].tile] + = this->MiscDisplayLayer[this->pitchDitches[pitchDitchID].tile] & 0xbfff; + this->MiscDisplayLayer[this->pitchDitches[pitchDitchID].tile] + = this->MiscDisplayLayer[this->pitchDitches[pitchDitchID].tile] & 0xdfff; + this->ChangedLayer[this->pitchDitches[pitchDitchID].tile] = 2; + return pitchDitchID; + } + return 0; + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/placePositiveFearfactor.cpp b/src/OpenSHC/Map/TileMapState/placePositiveFearfactor.cpp new file mode 100644 index 0000000000..6a02a5734a --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/placePositiveFearfactor.cpp @@ -0,0 +1,55 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Map/Buildings/BuildingsState.func.hpp" +#include "OpenSHC/UI/BottomLeftTextDisplayState.func.hpp" + +#include "OpenSHC/Globals/DAT_BottomLeftTextDisplayState.hpp" +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_GameState.hpp" +#include "OpenSHC/Globals/DAT_GameSynchronyState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_BUILDING; + + // FUNCTION: STRONGHOLDCRUSADER 0x00506F40 + void TileMapState::placePositiveFearfactor(int playerID, uint x, uint y, undefined4 buildingType, + undefined4 variation, uint buildingSize, undefined4 param_7, undefined4 high) + { + int buildingSizeTileIndex = 0; + int buildingID = MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::setupBuildingData, DAT_BuildingsState::ptr)( + playerID, x, y, high, (BuildingType)(short)buildingType, buildingSize, playerID, (short)variation); + this->placedBuildingID = buildingID; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)( + buildingSizeTileIndex, buildingSize); + int tileUnk = DAT_ViewportRenderState::instance.translationMatrix[this->buildingY + y].addXgetTile + + this->buildingX + x; + if (buildingSizeTileIndex < 36) { + DAT_BuildingsState::instance.buildings[buildingID].tileRefs[buildingSizeTileIndex] = tileUnk; + } + this->HeightLayer[tileUnk] = (byte)high; + this->LogicLayer[tileUnk] = this->LogicLayer[tileUnk] | L_BUILDING; + this->BuildingLayer[tileUnk] = (short)buildingID; + buildingSizeTileIndex++; + this->ChangedLayer[tileUnk] = 2; + } while (buildingSizeTileIndex < this->constructionTileCount); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::setMiscDisplayLayer, this)(buildingID); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::updatePathLinkagesForBuilding, this)(buildingID); + if (playerID == DAT_GameSynchronyState::instance.currentPlayerSlotID + && (int)DAT_BuildingsState::instance.buildings[buildingID].buildingTypeBasedEmployeeCount + > DAT_GameState::instance.playerDataArray[playerID].availablePeasantsAtFire + && (DAT_GameState::instance.playerDataArray[playerID].populationCap + <= DAT_GameState::instance.playerDataArray[playerID].currentPopulation + || DAT_GameState::instance.playerDataArray[playerID].popularity < 5000)) { + MACRO_CALL_MEMBER(OpenSHC::UI::BottomLeftTextDisplayState_Func::setBottomLeftTextDisplayText, + DAT_BottomLeftTextDisplayState::ptr)( + 1, 0x4d, 1, 0, 100, 6000); + } + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/placeQuarry.cpp b/src/OpenSHC/Map/TileMapState/placeQuarry.cpp new file mode 100644 index 0000000000..7d1bbcf20c --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/placeQuarry.cpp @@ -0,0 +1,119 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/AI/AIVState.func.hpp" +#include "OpenSHC/Map/Buildings/BuildingsState.func.hpp" +#include "OpenSHC/UI/BottomLeftTextDisplayState.func.hpp" +#include "OpenSHC/Commands/MappersEnum.hpp" +#include "OpenSHC/Map/Buildings/BuildingType.hpp" +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +#include "OpenSHC/Globals/DAT_AIVState.hpp" +#include "OpenSHC/Globals/DAT_BottomLeftTextDisplayState.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" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_BUILDING; + + using OpenSHC::Commands::MappersEnum; + using OpenSHC::Map::Buildings::BuildingType; + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x00508250 + void TileMapState::placeQuarry(int playerID, uint x, uint y, undefined4 buildingType, uint buildingSize, + int buildingOrientation, uint high) + { + int index = 0; + int uid = DAT_GameCore::instance.uniqueGameObjectTracker; + int quarryID = MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::setupBuildingData, DAT_BuildingsState::ptr)(playerID, x, y, high, + (BuildingType)(int)(short)buildingType, buildingSize, playerID, buildingOrientation); + this->placedBuildingID = quarryID; + DAT_BuildingsState::instance.buildings[quarryID].uidWhenPlaced = uid; + + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)(index, buildingSize); + int tileUnk = DAT_ViewportRenderState::instance.translationMatrix[this->buildingY + y].addXgetTile + x + this->buildingX; + index++; + this->HeightLayer[tileUnk] = (byte)high; + this->LogicLayer[tileUnk] = this->LogicLayer[tileUnk] | L_BUILDING; + this->BuildingLayer[tileUnk] = (short)quarryID; + this->BuildingWasLayer[tileUnk] = (uchar)buildingType; + this->ChangedLayer[tileUnk] = 2; + } while (index < this->constructionTileCount); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::setMiscDisplayLayer, this)(quarryID); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::updatePathLinkagesForBuilding, this)(quarryID); + + /* nine attempts at a pile location, moving further from the quarry each time */ + int attempt = 1; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::findQuarryPileLocation, DAT_BuildingsState::ptr)( + playerID, x, y, buildingSize, 2, attempt, OpenSHC::Commands::M_MAPPER_QUARRYPILE); + if (this->buildingPlacementFail == FALSE) { + break; + } + attempt++; + } while (attempt < 10); + if (this->buildingPlacementFail != FALSE) { + return; + } + + /* x/y now name the pile corner */ + x = x + DAT_BuildingsState::instance.DAT_TempXOffset; + y = y + DAT_BuildingsState::instance.DAT_TempYOffset; + int tileIndex = 0; + int lowest = 1000; + int highest = 0; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)(tileIndex, 2); + int tileHeight = this->HeightLayer[DAT_ViewportRenderState::instance.translationMatrix[this->buildingY + y].addXgetTile + + x + this->buildingX]; + if (tileHeight > highest) { + highest = tileHeight; + } + if (tileHeight < lowest) { + lowest = tileHeight; + } + tileIndex++; + } while (tileIndex < this->constructionTileCount); + high = (highest - lowest) / 2 + lowest; + + tileIndex = 0; + int pileID = MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::setupBuildingData, DAT_BuildingsState::ptr)(playerID, x, y, + high, OpenSHC::Map::Buildings::BT_QUARRYSTOCKPILE, 2, playerID, buildingOrientation); + MACRO_CALL_MEMBER(OpenSHC::AI::AIVState_Func::incrementStructureHeatMapTile, DAT_AIVState::ptr)(x, y); + DAT_BuildingsState::instance.buildings[pileID].uidWhenPlaced = uid; + DAT_BuildingsState::instance.buildings[quarryID].quarryStockpileID = (short)pileID; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)(tileIndex, 2); + int tileUnk = DAT_ViewportRenderState::instance.translationMatrix[this->buildingY + y].addXgetTile + x + this->buildingX; + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::resetTileAndClearMoat, this)(tileUnk); + this->HeightLayer[tileUnk] = (byte)high; + this->LogicLayer[tileUnk] = this->LogicLayer[tileUnk] | L_BUILDING; + this->BuildingLayer[tileUnk] = (short)pileID; + tileIndex++; + this->BuildingWasLayer[tileUnk] = (uchar)buildingType; + this->ChangedLayer[tileUnk] = 2; + } while (tileIndex < this->constructionTileCount); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::setMiscDisplayLayer, this)(pileID); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::updatePathLinkagesForBuilding, this)(pileID); + + if (playerID == DAT_GameSynchronyState::instance.currentPlayerSlotID + && DAT_BuildingsState::instance.buildings[pileID].buildingTypeBasedEmployeeCount + > DAT_GameState::instance.playerDataArray[playerID].availablePeasantsAtFire + && (DAT_GameState::instance.playerDataArray[playerID].populationCap + <= DAT_GameState::instance.playerDataArray[playerID].currentPopulation + || DAT_GameState::instance.playerDataArray[playerID].popularity < 5000)) { + /* "Not enough workers available to run this building." */ + MACRO_CALL_MEMBER(OpenSHC::UI::BottomLeftTextDisplayState_Func::setBottomLeftTextDisplayText, + DAT_BottomLeftTextDisplayState::ptr)( + 1, 0x4d, 1, 0, 100, 6000); + } + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/placeRock.cpp b/src/OpenSHC/Map/TileMapState/placeRock.cpp new file mode 100644 index 0000000000..928bd93ad4 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/placeRock.cpp @@ -0,0 +1,142 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Map/LandscapeState.func.hpp" +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" + +#include "OpenSHC/Globals/DAT_LandscapeState.hpp" +#include "OpenSHC/Globals/DAT_PathFindingState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_BORDER; + using OpenSHC::Map::LogicHelpers::L_BORDER_EDGE; + using OpenSHC::Map::LogicHelpers::L_BOULDERS; + using OpenSHC::Map::LogicHelpers::L_BUILDING; + using OpenSHC::Map::LogicHelpers::L_FORD; + using OpenSHC::Map::LogicHelpers::L_IRON; + using OpenSHC::Map::LogicHelpers::L_MARSH; + using OpenSHC::Map::LogicHelpers::L_MOAT; + using OpenSHC::Map::LogicHelpers::L_OIL; + using OpenSHC::Map::LogicHelpers::L_PEBBLES; + using OpenSHC::Map::LogicHelpers::L_PLAIN2_AND_PITCH; + using OpenSHC::Map::LogicHelpers::L_RIVER; + using OpenSHC::Map::LogicHelpers::L_ROCKY; + using OpenSHC::Map::LogicHelpers::L_SEA; + + // FUNCTION: STRONGHOLDCRUSADER 0x004FB4D0 + void TileMapState::placeRock(uint x, uint y, uint kind) + { + int rockType = 0; + int size = 1; + if (x > 399) { + return; + } + if (y > 399) { + return; + } + if (DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[y * 400 + x] == 0) { + return; + } + /* every rock kind has its own footprint size and rock type */ + if ((short)kind == 0) { + rockType = 1; + } else if ((short)kind == 1) { + rockType = 2; + } else if ((short)kind == 2) { + rockType = 3; + } else if ((short)kind == 3) { + rockType = 4; + } else if ((short)kind == 4) { + size = 2; + rockType = 5; + } else if ((short)kind == 5) { + size = 2; + rockType = 6; + } else if ((short)kind == 6) { + size = 2; + rockType = 7; + } else if ((short)kind == 7) { + size = 2; + rockType = 8; + } else if ((short)kind == 8) { + size = 3; + rockType = 9; + } else if ((short)kind == 9) { + size = 3; + rockType = 0xa; + } else if ((short)kind == 0xa) { + size = 3; + rockType = 0xb; + } else if ((short)kind == 0xb) { + size = 3; + rockType = 0xc; + } else { + if ((short)kind == 0xc) { + rockType = 0xd; + } else if ((short)kind == 0xd) { + rockType = 0xe; + } else if ((short)kind == 0xe) { + rockType = 0xf; + } else if ((short)kind == 0xf) { + rockType = 0x10; + } + if (rockType != 0) { + size = 4; + } + } + + /* the original reuses the kind parameter to hold the lowest height under the footprint */ + kind = 1000; + int highest = 0; + int index = 0; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)(index, size); + int tile = DAT_ViewportRenderState::instance.translationMatrix[this->buildingY + y].addXgetTile + + this->buildingX + x; + if ((this->LogicLayer[tile] & (L_BORDER | L_BORDER_EDGE)) != 0) { + return; + } + if ((this->LogicLayer[tile] & L_BUILDING) != 0) { + return; + } + if (this->OrganismLayer[tile] != 0) { + return; + } + if (highest < this->HeightLayer[tile]) { + highest = this->HeightLayer[tile]; + } + if (this->HeightLayer[tile] < (int)kind) { + kind = this->HeightLayer[tile]; + } + index++; + } while (index < this->constructionTileCount); + + byte height = (char)((int)(highest - kind) / 2) + (char)kind; + int rockID = MACRO_CALL_MEMBER(OpenSHC::Map::LandscapeState_Func::createRock, DAT_LandscapeState::ptr)( + x, y, rockType, size, this->rockOrientation); + index = 0; + short organism = (short)rockID + 2000; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)(index, size); + index++; + int tile = DAT_ViewportRenderState::instance.translationMatrix[this->buildingY + y].addXgetTile + + this->buildingX + x; + this->HeightLayer[tile] = height; + this->DefaultHeightLayer[tile] = height; + this->LogicLayer[tile] = this->LogicLayer[tile] + & ~(L_SEA | L_PLAIN2_AND_PITCH | L_BOULDERS | L_PEBBLES | L_IRON | L_RIVER | L_FORD | L_MARSH | L_MOAT + | L_OIL); + this->Logic2Layer[tile] = 0; + this->LogicLayer[tile] = this->LogicLayer[tile] | L_ROCKY; + this->OrganismLayer[tile] = organism; + } while (index < this->constructionTileCount); + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::updateWalkAndPathLayer, + DAT_PathFindingState::ptr)(9, x, y); + this->forceUpdateMacroLayerFlag = 1; + DAT_PathFindingState::instance.toggleUpdateSeparateAreaTileMap = 1; + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/placeSiegeTent.cpp b/src/OpenSHC/Map/TileMapState/placeSiegeTent.cpp new file mode 100644 index 0000000000..60a163e795 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/placeSiegeTent.cpp @@ -0,0 +1,55 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Map/Buildings/BuildingsState.func.hpp" +#include "OpenSHC/UI/BottomLeftTextDisplayState.func.hpp" + +#include "OpenSHC/Globals/DAT_BottomLeftTextDisplayState.hpp" +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_GameState.hpp" +#include "OpenSHC/Globals/DAT_GameSynchronyState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_BUILDING; + + // FUNCTION: STRONGHOLDCRUSADER 0x00506E10 + void TileMapState::placeSiegeTent( + int playerID, uint x, uint y, undefined4 buildingType, uint buildingSize, int param_6, undefined4 height) + { + int buildingID = MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::setupBuildingData, DAT_BuildingsState::ptr)( + playerID, x, y, height, (BuildingType)(short)buildingType, buildingSize, playerID, param_6); + this->placedBuildingID = buildingID; + int buildingSizeTileIndex = 0; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)( + buildingSizeTileIndex, buildingSize); + int tile = DAT_ViewportRenderState::instance.translationMatrix[this->buildingY + y].addXgetTile + + this->buildingX + x; + if (buildingSizeTileIndex < 36) { + DAT_BuildingsState::instance.buildings[buildingID].tileRefs[buildingSizeTileIndex] = tile; + } + this->HeightLayer[tile] = (byte)height; + this->LogicLayer[tile] = this->LogicLayer[tile] | L_BUILDING; + this->BuildingLayer[tile] = (short)buildingID; + buildingSizeTileIndex++; + this->BuildingWasLayer[tile] = (uchar)(short)buildingType; + this->ChangedLayer[tile] = 2; + } while (buildingSizeTileIndex < this->constructionTileCount); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::setMiscDisplayLayer, this)(buildingID); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::updatePathLinkagesForBuilding, this)(buildingID); + if (playerID == DAT_GameSynchronyState::instance.currentPlayerSlotID + && DAT_GameState::instance.playerDataArray[playerID].availablePeasantsAtFire + < (int)DAT_BuildingsState::instance.buildings[buildingID].buildingTypeBasedEmployeeCount + && (DAT_GameState::instance.playerDataArray[playerID].populationCap + <= DAT_GameState::instance.playerDataArray[playerID].currentPopulation + || DAT_GameState::instance.playerDataArray[playerID].popularity < 5000)) { + MACRO_CALL_MEMBER(OpenSHC::UI::BottomLeftTextDisplayState_Func::setBottomLeftTextDisplayText, + DAT_BottomLeftTextDisplayState::ptr)(1, 0x4d, 1, 0, 100, 6000); + } + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/placeSiegetowerPlaced.cpp b/src/OpenSHC/Map/TileMapState/placeSiegetowerPlaced.cpp new file mode 100644 index 0000000000..aed064449a --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/placeSiegetowerPlaced.cpp @@ -0,0 +1,44 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Map/Buildings/BuildingsState.func.hpp" + +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_KEEP_NON_MANOR_HOUSE; + + using OpenSHC::Map::LogicHelpers::L_KEEP_NON_MANOR_HOUSE; + + // FUNCTION: STRONGHOLDCRUSADER 0x00506D40 + void TileMapState::placeSiegetowerPlaced( + int param_1, uint param_2, uint param_3, undefined4 param_4, uint param_5, int param_6, undefined4 param_7) + { + int buildingID = MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::setupBuildingData, DAT_BuildingsState::ptr)( + param_1, param_2, param_3, param_7, (BuildingType)(short)param_4, param_5, param_1, param_6); + this->placedBuildingID = buildingID; + int buildingSizeTileIndex = 0; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)( + buildingSizeTileIndex, param_5); + int tile = DAT_ViewportRenderState::instance.translationMatrix[this->buildingY + param_3].addXgetTile + + this->buildingX + param_2; + if (buildingSizeTileIndex < 36) { + DAT_BuildingsState::instance.buildings[buildingID].tileRefs[buildingSizeTileIndex] = tile; + } + this->HeightLayer[tile] = (byte)param_7; + this->LogicLayer[tile] = this->LogicLayer[tile] | L_KEEP_NON_MANOR_HOUSE; + this->BuildingLayer[tile] = (short)buildingID; + buildingSizeTileIndex++; + this->BuildingWasLayer[tile] = (uchar)(short)param_4; + this->ChangedLayer[tile] = 2; + } while (buildingSizeTileIndex < this->constructionTileCount); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::setMiscDisplayLayer, this)(buildingID); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::updatePathLinkagesForBuilding, this)(buildingID); + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/placeStockpile.cpp b/src/OpenSHC/Map/TileMapState/placeStockpile.cpp new file mode 100644 index 0000000000..42a27a1ce6 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/placeStockpile.cpp @@ -0,0 +1,87 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Map/Buildings/BuildingsState.func.hpp" +#include "OpenSHC/UI/BottomLeftTextDisplayState.func.hpp" + +#include "OpenSHC/Globals/DAT_BottomLeftTextDisplayState.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" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_BUILDING; + using OpenSHC::Map::LogicHelpers::L_STOCKPILEUnk; + using OpenSHC::Map::LogicHelpers::L_WALL_OR_GATEHOUSE; + + // FUNCTION: STRONGHOLDCRUSADER 0x00508540 + void TileMapState::placeStockpile( + int playerID, int x, int y, undefined4 buildingType, undefined4 param_5, int variation, int averageHeight) + { + int uid = DAT_GameCore::instance.uniqueGameObjectTracker; + byte height = (char)averageHeight + 10; + byte wallOwner = (char)playerID - 1; + int type = (short)buildingType; + + int buildingID; + for (int part = 0; part < 4; part++) { + buildingID = MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::setupBuildingData, DAT_BuildingsState::ptr)(playerID, + DAT_TerrainDefinedData::instance.Stockpile_BuildingPartsOffsets[part].x + x, + DAT_TerrainDefinedData::instance.Stockpile_BuildingPartsOffsets[part].y + y, averageHeight + 10, + (BuildingType)type, 2, playerID, variation); + DAT_BuildingsState::instance.buildings[buildingID].uidWhenPlaced = uid; + DAT_BuildingsState::instance.buildings[buildingID].field125_0x190 = part + 1; + int index = 0; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)(index, 2); + index++; + int tile + = DAT_ViewportRenderState::instance + .translationMatrix[DAT_TerrainDefinedData::instance.Stockpile_BuildingPartsOffsets[part].y + + this->buildingY + y] + .addXgetTile + + DAT_TerrainDefinedData::instance.Stockpile_BuildingPartsOffsets[part].x + x + this->buildingX; + this->HeightLayer[tile] = height; + /* the stockpile body itself cannot be walked over */ + this->LogicLayer[tile] = this->LogicLayer[tile] | (L_STOCKPILEUnk | L_WALL_OR_GATEHOUSE | L_BUILDING); + this->WallOwnerLayer[tile] = this->WallOwnerLayer[tile] & 0xf8 | wallOwner; + this->BuildingLayer[tile] = (ushort)buildingID; + this->BuildingWasLayer[tile] = (uchar)buildingType; + this->ChangedLayer[tile] = 2; + } while (index < this->constructionTileCount); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::updatePathLinkagesForBuilding, this)(buildingID); + } + + this->placedBuildingID = buildingID; + /* the surrounding tiles carry the stockpile graphic but stay walkable */ + for (int slot = 0; slot < 9; slot++) { + int tile = DAT_ViewportRenderState::instance + .translationMatrix[DAT_TerrainDefinedData::instance.StockpilePathableOffsets[slot].y + y] + .addXgetTile + + DAT_TerrainDefinedData::instance.StockpilePathableOffsets[slot].x + x; + this->LogicLayer[tile] = this->LogicLayer[tile] | (L_STOCKPILEUnk | L_WALL_OR_GATEHOUSE); + this->HeightLayer[tile] = height; + this->AlphaGFXLayer[tile] = (ushort)buildingID; + this->BuildingWasLayer[tile] = (uchar)buildingType; + this->WallOwnerLayer[tile] = this->WallOwnerLayer[tile] & 0xf8 | wallOwner; + this->ChangedLayer[tile] = 2; + } + + if (playerID == DAT_GameSynchronyState::instance.currentPlayerSlotID + && DAT_GameState::instance.playerDataArray[playerID].availablePeasantsAtFire + < DAT_BuildingsState::instance.buildings[buildingID].buildingTypeBasedEmployeeCount + && (DAT_GameState::instance.playerDataArray[playerID].populationCap + <= DAT_GameState::instance.playerDataArray[playerID].currentPopulation + || DAT_GameState::instance.playerDataArray[playerID].popularity < 5000)) { + MACRO_CALL_MEMBER(OpenSHC::UI::BottomLeftTextDisplayState_Func::setBottomLeftTextDisplayText, + DAT_BottomLeftTextDisplayState::ptr)(1, 0x4d, 1, 0, 100, 6000); + } + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/placeTower.cpp b/src/OpenSHC/Map/TileMapState/placeTower.cpp new file mode 100644 index 0000000000..4d7c03aaf5 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/placeTower.cpp @@ -0,0 +1,56 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Map/Buildings/BuildingsState.func.hpp" + +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_GameCore.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_BUILDING; + using OpenSHC::Map::LogicHelpers::L_KEEP_NON_MANOR_HOUSE; + + // FUNCTION: STRONGHOLDCRUSADER 0x00507130 + void TileMapState::placeTower( + int param_1, uint param_2, uint param_3, undefined4 param_4, uint size, int param_6, undefined4 param_7) + { + int uniqueID = DAT_GameCore::instance.uniqueGameObjectTracker; + int index = 0; + int buildingID = MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::setupBuildingData, DAT_BuildingsState::ptr)( + param_1, param_2, param_3, param_7, (BuildingType)(short)param_4, size, param_1, param_6); + this->placedBuildingID = buildingID; + DAT_BuildingsState::instance.buildings[buildingID].uidWhenPlaced = uniqueID; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)(index, size); + int tileUnk = DAT_ViewportRenderState::instance.translationMatrix[this->buildingY + param_3].addXgetTile + + param_2 + this->buildingX; + if (index < 36) { + DAT_BuildingsState::instance.buildings[buildingID].tileRefs[index] = tileUnk; + } + this->HeightLayer[tileUnk] = (byte)param_7; + if (DAT_TerrainDefinedData::instance.TowerTileOffsetsBySize[size][0] == index) { + this->LogicLayer[tileUnk] = this->LogicLayer[tileUnk] | L_BUILDING; + } else if (DAT_TerrainDefinedData::instance.TowerTileOffsetsBySize[size][1] == index) { + this->LogicLayer[tileUnk] = this->LogicLayer[tileUnk] | L_BUILDING; + } else if (DAT_TerrainDefinedData::instance.TowerTileOffsetsBySize[size][2] == index) { + this->LogicLayer[tileUnk] = this->LogicLayer[tileUnk] | L_BUILDING; + } else if (DAT_TerrainDefinedData::instance.TowerTileOffsetsBySize[size][3] == index) { + this->LogicLayer[tileUnk] = this->LogicLayer[tileUnk] | L_BUILDING; + } else { + this->LogicLayer[tileUnk] = this->LogicLayer[tileUnk] | L_KEEP_NON_MANOR_HOUSE; + } + this->BuildingLayer[tileUnk] = (short)buildingID; + index++; + this->BuildingWasLayer[tileUnk] = (uchar)param_4; + this->ChangedLayer[tileUnk] = 2; + } while (index < this->constructionTileCount); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::setMiscDisplayLayer, this)(buildingID); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::updatePathLinkagesForBuilding, this)(buildingID); + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/placeTree.cpp b/src/OpenSHC/Map/TileMapState/placeTree.cpp new file mode 100644 index 0000000000..082882c2f7 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/placeTree.cpp @@ -0,0 +1,98 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Map/LandscapeState.func.hpp" +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" + +#include "OpenSHC/Globals/DAT_LandscapeState.hpp" +#include "OpenSHC/Globals/DAT_PathFindingState.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_BORDER; + using OpenSHC::Map::LogicHelpers::L_BORDER_EDGE; + using OpenSHC::Map::LogicHelpers::L_BOULDERS; + using OpenSHC::Map::LogicHelpers::L_BUILDING; + using OpenSHC::Map::LogicHelpers::L_FORD; + using OpenSHC::Map::LogicHelpers::L_IRON; + using OpenSHC::Map::LogicHelpers::L_KEEP_NON_MANOR_HOUSE; + using OpenSHC::Map::LogicHelpers::L_MARSH; + using OpenSHC::Map::LogicHelpers::L_MOAT; + using OpenSHC::Map::LogicHelpers::L_PEBBLES; + using OpenSHC::Map::LogicHelpers::L_PLAIN1_AND_FARM; + using OpenSHC::Map::LogicHelpers::L_RIVER; + using OpenSHC::Map::LogicHelpers::L_ROCKY; + using OpenSHC::Map::LogicHelpers::L_SEA; + using OpenSHC::Map::LogicHelpers::L_TREE; + using OpenSHC::Map::LogicHelpers::L_TREE_VARIATION; + using OpenSHC::Map::LogicHelpers::L_WALL_OR_GATEHOUSE; + + // FUNCTION: STRONGHOLDCRUSADER 0x00515DA0 + void TileMapState::placeTree(uint x, uint y, undefined4 treeType) + { + if (x > 399 || y > 399) { + return; + } + if (DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[y * 400 + x] == 0) { + return; + } + + int stage = MACRO_CALL_MEMBER( + OpenSHC::Map::LandscapeState_Func::getValueFrom0UpTo3ForTreeTypeAndTreeStage, DAT_LandscapeState::ptr)( + MACRO_CALL_MEMBER(OpenSHC::Map::LandscapeState_Func::mapUITreeTypeToLogicalTreeType, + DAT_LandscapeState::ptr)((short)treeType), + 3); + uint baseTile = DAT_ViewportRenderState::instance.translationMatrix[y].addXgetTile + x; + int brushSize = DAT_TerrainDefinedData::instance.BrushSizeArray[stage]; + if ((this->LogicLayer[baseTile] + & (L_SEA | L_PLAIN1_AND_FARM | L_BORDER | L_BORDER_EDGE | L_ROCKY | L_WALL_OR_GATEHOUSE | L_BUILDING + | L_TREE_VARIATION | L_BOULDERS | L_PEBBLES | L_IRON | L_RIVER | L_FORD | L_KEEP_NON_MANOR_HOUSE + | L_MARSH | L_MOAT)) + != 0) { + return; + } + + uint tile = baseTile; + uint brushY = y; + int index = 0; + if (brushSize > 0) { + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getTileForBrush, this)( + 1, index, (int*)&tile, (int*)&brushY, baseTile, y); + if ((this->LogicLayer[tile] & L_BORDER) != 0) { + break; + } + if ((this->LogicLayer[tile] & (L_WALL_OR_GATEHOUSE | L_BUILDING | L_RIVER | L_KEEP_NON_MANOR_HOUSE)) + != 0) { + return; + } + if ((this->LogicLayer[tile] & L_ROCKY) != 0) { + return; + } + if (this->OrganismLayer[tile] != 0) { + return; + } + index++; + } while (index < brushSize); + } + + int treeID = MACRO_CALL_MEMBER(OpenSHC::Map::LandscapeState_Func::createTree, DAT_LandscapeState::ptr)(x, y, + (TreeType)(short)MACRO_CALL_MEMBER(OpenSHC::Map::LandscapeState_Func::mapUITreeTypeToLogicalTreeType, + DAT_LandscapeState::ptr)((short)treeType), + stage, 0, 0, 3); + this->LogicLayer[DAT_LandscapeState::instance.trees[treeID].tile] + = this->LogicLayer[DAT_LandscapeState::instance.trees[treeID].tile] & ~L_ROCKY; + this->LogicLayer[DAT_LandscapeState::instance.trees[treeID].tile] + = this->LogicLayer[DAT_LandscapeState::instance.trees[treeID].tile] | L_TREE; + this->OrganismLayer[DAT_LandscapeState::instance.trees[treeID].tile] = (short)treeID; + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::applyTreeBrushToLogicalLayer, this)(treeID, 0); + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::updatePathLinkagesInAllEightDirections, + DAT_PathFindingState::ptr)( + DAT_LandscapeState::instance.trees[treeID].yPosition, DAT_LandscapeState::instance.trees[treeID].tile); + DAT_PathFindingState::instance.toggleUpdateSeparateAreaTileMap = 1; + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/placeTunnelersguild.cpp b/src/OpenSHC/Map/TileMapState/placeTunnelersguild.cpp new file mode 100644 index 0000000000..ce2ea55cc8 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/placeTunnelersguild.cpp @@ -0,0 +1,93 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Map/Buildings/BuildingsState.func.hpp" +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" +#include "OpenSHC/Map/Buildings/BuildingType.hpp" + +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_GameCore.hpp" +#include "OpenSHC/Globals/DAT_PathFindingState.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::Buildings::BuildingType; + + // FUNCTION: STRONGHOLDCRUSADER 0x00507E00 + void TileMapState::placeTunnelersguild( + int param_1, int* param_2, uint param_3, undefined4 param_4, uint param_5, int param_6, undefined4 param_7) + { + int* piVar1; + int iVar2; + int buildingID; + int iVar3; + uint y; + uint x; + int iVar4; + int iVar5; + int local_8; + piVar1 = param_2; + iVar5 = DAT_GameCore::instance.uniqueGameObjectTracker; + iVar4 = 0; + if (param_6 == 0xf) { + local_8 = 0; + } else { + local_8 = param_6 / 2; + } + iVar2 = MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::setupBuildingData, + DAT_BuildingsState::ptr)(param_1, (uint)(param_2), param_3, (undefined4)((int)(param_7)), + (BuildingType)((int)((short)param_4)), param_5, param_1, 0xf); + buildingID = (int)(short)iVar2; + this->placedBuildingID = buildingID; + DAT_BuildingsState::instance.buildings[buildingID].uidWhenPlaced = iVar5; + param_2 = &DAT_BuildingsState::instance.buildings[buildingID].tileRefs[0]; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)( + iVar4, (int)(param_5)); + iVar3 = DAT_ViewportRenderState::instance.translationMatrix[this->buildingY + param_3].addXgetTile + + this->buildingX + (int)piVar1; + *param_2 = iVar3; + this->HeightLayer[iVar3] = (byte)param_7; + this->LogicLayer[iVar3] = this->LogicLayer[iVar3] | 1024; + this->BuildingLayer[iVar3] = (short)iVar2; + iVar4 = iVar4 + 1; + param_2 = param_2 + 1; + this->BuildingWasLayer[iVar3] = (uchar)param_4; + this->ChangedLayer[iVar3] = 2; + } while (iVar4 < this->constructionTileCount); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::setMiscDisplayLayer, this)(buildingID); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::updatePathLinkagesForBuilding, this)(buildingID); + x = (int)piVar1 + DAT_TerrainDefinedData::instance.BuildingPartsOffsets[local_8][1].x; + y = param_3 + DAT_TerrainDefinedData::instance.BuildingPartsOffsets[local_8][1].y; + iVar4 = MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::setupBuildingData, DAT_BuildingsState::ptr)( + param_1, x, y, (undefined4)((int)(param_7)), OpenSHC::Map::Buildings::BT_PARADEGROUND5, 5, param_1, 0xf); + iVar2 = (int)(short)iVar4; + DAT_BuildingsState::instance.buildings[iVar2].uidWhenPlaced = iVar5; + DAT_BuildingsState::instance.buildings[iVar2].quarryStockpileID = (undefined2)this->placedBuildingID; + param_5 = 0; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)( + param_5, (int)(DAT_BuildingsState::instance.buildings[iVar2].widthOrHeight)); + iVar5 = DAT_ViewportRenderState::instance.translationMatrix[this->buildingY + y].addXgetTile + + this->buildingX + x; + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::resetTileAndClearMoat, this)(iVar5); + this->HeightLayer[iVar5] = (byte)param_7; + this->BuildingLayer[iVar5] = (short)iVar4; + param_5 = param_5 + 1; + this->BuildingWasLayer[iVar5] = (uchar)param_4; + this->ChangedLayer[iVar5] = 2; + } while ((int)param_5 < this->constructionTileCount); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::setMiscDisplayLayer, this)(iVar2); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::updatePathLinkagesForBuilding, this)(iVar2); + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::updateWalkAndPathLayer, + DAT_PathFindingState::ptr)(8, x, y); + MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::setupTunnelersGuildCampgroundPositions, + DAT_BuildingsState::ptr)(param_1); + return; + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/placeWalls.cpp b/src/OpenSHC/Map/TileMapState/placeWalls.cpp new file mode 100644 index 0000000000..ddff49a81b --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/placeWalls.cpp @@ -0,0 +1,274 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Game/GameStateStructures.func.hpp" +#include "OpenSHC/Map/Buildings/BuildingsState.func.hpp" +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" +#include "OpenSHC/Map/WallAndPitchState.func.hpp" +#include "OpenSHC/UI/MinimapViewState.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_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_GameState.hpp" +#include "OpenSHC/Globals/DAT_GameSynchronyState.hpp" +#include "OpenSHC/Globals/DAT_LandscapeState.hpp" +#include "OpenSHC/Globals/DAT_MinimapViewState.hpp" +#include "OpenSHC/Globals/DAT_PathFindingState.hpp" +#include "OpenSHC/Globals/DAT_UnitsState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" +#include "OpenSHC/Globals/DAT_WallAndPitchState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_BOULDERS; + using OpenSHC::Map::LogicHelpers::L_CRENEL; + using OpenSHC::Map::LogicHelpers::L_CRENEL_VARIATIONUnk; + using OpenSHC::Map::LogicHelpers::L_IRON; + using OpenSHC::Map::LogicHelpers::L_PEBBLES; + using OpenSHC::Map::LogicHelpers::L_PLAIN2_AND_PITCH; + using OpenSHC::Map::LogicHelpers::L_STAIRS; + using OpenSHC::Map::LogicHelpers::L_TREE; + using OpenSHC::Map::LogicHelpers::L_UNKNOWN_WALL_RELATED; + using OpenSHC::Map::LogicHelpers::L_WALL_OR_GATEHOUSE; + + using OpenSHC::Map::Units::UnitType; + using OpenSHC::Map::Units::States::UnitState; + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x00502F30 + void TileMapState::placeWalls( + int playerID, uint x1, uint y1, uint x2, uint y2, MappersEnum wallType, int tileCountUnk) + { + int budget = 0; + int wallCount = 0; + int placed = 0; + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::validateWallBuildPath, this)( + playerID, x1, y1, x2, y2, wallType); + if (this->illegalBuild != FALSE) { + return; + } + + this->constructionTileCount = MACRO_CALL_MEMBER( + OpenSHC::Game::GameStateStructures_Func::getWallTilesThatCanBeBuilt, DAT_GameState::ptr)(playerID, 4); + int overshoot = 2; + if ((short)wallType == OpenSHC::Commands::M_MAPPER_STAIR) { + budget = this->maxWallHeightInPath; + } + if (playerID == DAT_GameSynchronyState::instance.currentPlayerSlotID) { + MACRO_CALL_MEMBER( + OpenSHC::Map::WallAndPitchState_Func::resetWallPlacementInfo, DAT_WallAndPitchState::ptr)(); + } + + int upY = y1 - y2; + int downY = y2 - y1; + int rightX = x2 - x1; + int* translation = &DAT_ViewportRenderState::instance.translationMatrix[y1].addXgetTile; + uint x = x1; + int leftX = x1 - x2; + bool stairAborted = false; + do { + if ((short)wallType == OpenSHC::Commands::M_MAPPER_STAIR && budget < 0x18) { + stairAborted = true; + break; + } + if (tileCountUnk <= placed || this->constructionTileCount < wallCount) { + break; + } + placed++; + int tile = *translation + x; + bool towerNeighbours = false; + if ((short)wallType == OpenSHC::Commands::M_MAPPER_STAIR + && (this->LogicLayer[tile] & L_WALL_OR_GATEHOUSE) != 0) { + stairAborted = true; + break; + } + /* a wall dragged over a crenel replaces it without counting against the tally */ + bool overCrenel = false; + if ((short)wallType == OpenSHC::Commands::M_MAPPER_WALL && (this->LogicLayer[tile] & L_CRENEL) != 0) { + overCrenel = true; + } + if ((this->LogicLayer[tile] & L_WALL_OR_GATEHOUSE) == 0 || this->DamageLayer[tile] != 0 || overCrenel) { + if (playerID == DAT_GameSynchronyState::instance.currentPlayerSlotID) { + MACRO_CALL_MEMBER(OpenSHC::Map::WallAndPitchState_Func::addWallPlacementInfoForTile, + DAT_WallAndPitchState::ptr)(tile); + } + if (this->DamageLayer[tile] != 0 || overCrenel) { + this->DamageLayer[tile] = 0; + this->HeightLayer[tile] = this->DefaultHeightLayer[tile]; + if (overCrenel) { + this->LogicLayer[tile] + = this->LogicLayer[tile] & ~(L_CRENEL | L_CRENEL_VARIATIONUnk) | L_WALL_OR_GATEHOUSE; + } + } + + bool applyWall = true; + bool updateLinkages = true; + if ((short)wallType == OpenSHC::Commands::M_MAPPER_WALL) { + this->HeightLayer[tile] = this->HeightLayer[tile] + 0x5a; + } else if ((short)wallType == OpenSHC::Commands::M_MAPPER_WOODWALL) { + this->HeightLayer[tile] = this->HeightLayer[tile] + 0x3c; + } else if ((short)wallType == OpenSHC::Commands::M_MAPPER_CRENAL) { + this->LogicLayer[tile] = this->LogicLayer[tile] | L_CRENEL; + BOOLEnum onlyTowers = MACRO_CALL_MEMBER( + OpenSHC::Map::TileMapState_Func::hasOnlyTowerNeighborsNoWalls, this)(tile, y1); + if (onlyTowers == FALSE) { + this->HeightLayer[tile] = this->HeightLayer[tile] + 0x62; + } else { + this->HeightLayer[tile] = this->HeightLayer[tile] + 0x44; + } + towerNeighbours = onlyTowers != FALSE; + /* a crenel on an odd tile of one axis carries the alternate variation */ + if (((x & 1) == 0) != ((y1 & 1) == 0)) { + this->LogicLayer[tile] = this->LogicLayer[tile] | L_CRENEL_VARIATIONUnk; + } + } else if ((short)wallType == OpenSHC::Commands::M_MAPPER_STAIR) { + int steps = (budget - (int)(uint)this->HeightLayer[tile]) + -0x10; + if (steps > 0) { + this->LogicLayer[tile] = this->LogicLayer[tile] | L_STAIRS; + this->HeightLayer[tile] = this->HeightLayer[tile] + (char)steps; + } else { + applyWall = false; + updateLinkages = overCrenel; + } + } + + if (applyWall && !overCrenel) { + wallCount++; + this->LogicLayer[tile] + = this->LogicLayer[tile] & ~(L_UNKNOWN_WALL_RELATED | L_BOULDERS | L_PEBBLES | L_IRON) + | L_WALL_OR_GATEHOUSE; + if (this->UnitLayer[tile] != 0 + && DAT_UnitsState::instance.units[(short)this->UnitLayer[tile]].unitType + == OpenSHC::Map::Units::UT_CHICKEN) { + int unitID = (short)this->UnitLayer[tile]; + DAT_UnitsState::instance.units[unitID].state.generic + = OpenSHC::Map::Units::States::US_DISAPPEAR; + DAT_UnitsState::instance.units[unitID].updateTickTracker = 0; + DAT_UnitsState::instance.units[unitID].disappearFadeAlphaCountdown = 0; + } + if ((this->LogicLayer[tile] & L_PLAIN2_AND_PITCH) != 0) { + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_PLAIN2_AND_PITCH; + this->HeightLayer[tile] = this->HeightLayer[tile] + 4; + } + if ((this->LogicLayer[tile] & L_TREE) != 0 && this->OrganismLayer[tile] < 2000) { + /* scrub is flattened by the wall, a real tree is left standing */ + switch (DAT_LandscapeState::instance.trees[this->OrganismLayer[tile]].treeType) { + case (TreeType)5: + case (TreeType)6: + case (TreeType)7: + case (TreeType)8: + case (TreeType)9: + case (TreeType)0xa: + case (TreeType)0xb: + case (TreeType)0xc: + case (TreeType)0xd: + case (TreeType)0xe: + case (TreeType)0x10: + case (TreeType)0x11: + case (TreeType)0x12: + case (TreeType)0x13: + DAT_LandscapeState::instance.trees[this->OrganismLayer[tile]].state = 3; + } + } + if ((short)wallType == OpenSHC::Commands::M_MAPPER_WOODWALL || towerNeighbours) { + this->LogicLayer[tile] = this->LogicLayer[tile] | L_UNKNOWN_WALL_RELATED; + } + this->WallOwnerLayer[tile] = this->WallOwnerLayer[tile] & 0xf8 | (char)playerID - 1U; + } + if (updateLinkages) { + MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::PathFindingState_Func::updatePathLinkagesInAllEightDirections, + DAT_PathFindingState::ptr)(y1, tile); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::clearMoat, this)(tile); + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::updateWalkAndPathLayer, + DAT_PathFindingState::ptr)(7, x, y1); + } + } + + int stepX = leftX; + if ((int)x < (int)x2) { + stepX = rightX; + } + int stepY = upY; + if ((int)y1 < (int)y2) { + stepY = downY; + } + if ((short)wallType == OpenSHC::Commands::M_MAPPER_STAIR) { + if (stepY < stepX) { + if ((int)x < (int)x2) { + leftX = leftX + 1; + x = x + 1; + rightX = rightX - 1; + } else { + leftX = leftX - 1; + x = x - 1; + rightX = rightX + 1; + } + } else if (stepY < 1) { + overshoot = overshoot - 1; + } else if ((int)y1 < (int)y2) { + y1 = y1 + 1; + translation = translation + 3; + upY = upY + 1; + downY = downY - 1; + } else { + y1 = y1 - 1; + translation = translation - 3; + upY = upY - 1; + downY = downY + 1; + } + } else { + if (stepX != 0) { + int advance = 1; + if ((int)x < (int)x2) { + leftX = leftX + 1; + rightX = rightX - 1; + } else { + leftX = leftX - 1; + advance = -1; + rightX = rightX + 1; + } + x = x + advance; + } + if (stepY != 0) { + if ((int)y1 < (int)y2) { + y1 = y1 + 1; + translation = translation + 3; + upY = upY + 1; + downY = downY - 1; + } else { + y1 = y1 - 1; + translation = translation - 3; + upY = upY - 1; + downY = downY + 1; + } + } + if (x == x2 && y1 == y2) { + overshoot = overshoot - 1; + } + } + if (budget > 0xf) { + budget = budget - 0x10; + } + } while (x != x2 || y1 != y2 || overshoot != 0); + + int woodCount; + int stoneCount; + if (!stairAborted && (short)wallType == OpenSHC::Commands::M_MAPPER_WOODWALL) { + stoneCount = 0; + woodCount = wallCount; + } else { + woodCount = 0; + stoneCount = wallCount; + } + MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::processWallBuildingLoss, + DAT_BuildingsState::ptr)(playerID, stoneCount, woodCount, 0); + DAT_PathFindingState::instance.toggleUpdateSeparateAreaTileMap = 1; + this->field204_0x554a30 = 1; + MACRO_CALL_MEMBER(OpenSHC::UI::MinimapViewState_Func::triggerMinimapRedraw, DAT_MinimapViewState::ptr)(1); + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/placeWheatfarm.cpp b/src/OpenSHC/Map/TileMapState/placeWheatfarm.cpp new file mode 100644 index 0000000000..92dd871f03 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/placeWheatfarm.cpp @@ -0,0 +1,95 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Map/Buildings/BuildingsState.func.hpp" +#include "OpenSHC/UI/BottomLeftTextDisplayState.func.hpp" +#include "OpenSHC/Map/Buildings/BuildingType.hpp" +#include "OpenSHC/Map/LogicHelpers/Logic1.hpp" +#include "OpenSHC/Map/LogicHelpers/Logic2.hpp" + +#include "OpenSHC/Globals/DAT_BottomLeftTextDisplayState.hpp" +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_GameState.hpp" +#include "OpenSHC/Globals/DAT_GameSynchronyState.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::Buildings::BuildingType; + using OpenSHC::Map::LogicHelpers::L_BUILDING; + using OpenSHC::Map::LogicHelpers::L_FARM_FIELD_WHEAT; + using OpenSHC::Map::LogicHelpers::L_NONE; + using OpenSHC::Map::LogicHelpers::L2_THICK_SCRUB; + + // FUNCTION: STRONGHOLDCRUSADER 0x00514F30 + void TileMapState::placeWheatfarm(int playerID, uint x, uint y, undefined4 buildingType, undefined4 param_5, + int variation, undefined4 averageHeight) + { + int index = 0; + int buildingID = MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::setupBuildingData, + DAT_BuildingsState::ptr)(playerID, x, y, averageHeight, (BuildingType)(short)buildingType, 3, playerID, + variation); + this->placedBuildingID = buildingID; + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::markBuildingFootprintFlag, this)(x, y, 9); + + /* the 36 field tiles, from one of two alternating layouts */ + for (int i = 0; i < 36; i++) { + DAT_BuildingsState::instance.buildings[buildingID].tileRefs[i] + = DAT_ViewportRenderState::instance + .translationMatrix[DAT_TerrainDefinedData::instance + .WheatFarmTiles[DAT_GameState::instance.playerDataArray[playerID] + .unkWheatFarmOrientation][i] + .y + + y] + .addXgetTile + + x + + DAT_TerrainDefinedData::instance + .WheatFarmTiles[DAT_GameState::instance.playerDataArray[playerID].unkWheatFarmOrientation][i] + .x; + } + DAT_GameState::instance.playerDataArray[playerID].unkWheatFarmOrientation++; + if (DAT_GameState::instance.playerDataArray[playerID].unkWheatFarmOrientation > 1) { + DAT_GameState::instance.playerDataArray[playerID].unkWheatFarmOrientation = 0; + } + + /* the farm house */ + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)(index, 3); + int tileUnk = DAT_ViewportRenderState::instance.translationMatrix[this->buildingY + y].addXgetTile + x + + this->buildingX; + this->HeightLayer[tileUnk] = (byte)averageHeight; + this->LogicLayer[tileUnk] = this->LogicLayer[tileUnk] | L_BUILDING; + this->BuildingLayer[tileUnk] = (short)buildingID; + this->BuildingWasLayer[tileUnk] = (uchar)buildingType; + this->ChangedLayer[tileUnk] = 2; + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::setTerrain, this)( + playerID, tileUnk, this->buildingY + y, 2, L_NONE, L2_THICK_SCRUB); + index++; + } while (index < this->constructionTileCount); + + for (int i = 0; i < 36; i++) { + int tileUnk = DAT_BuildingsState::instance.buildings[buildingID].tileRefs[i]; + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::resetTileAndClearMoat, this)(tileUnk); + this->LogicLayer[tileUnk] = this->LogicLayer[tileUnk] | L_FARM_FIELD_WHEAT; + this->BuildingLayer[tileUnk] = (short)buildingID; + this->BuildingWasLayer[tileUnk] = (uchar)buildingType; + this->ChangedLayer[tileUnk] = 2; + } + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::setMiscDisplayLayer, this)(buildingID); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::updatePathLinkagesForBuilding, this)(buildingID); + + /* not enough idle peasants for the workers: tell the local player */ + if (playerID == DAT_GameSynchronyState::instance.currentPlayerSlotID + && DAT_BuildingsState::instance.buildings[buildingID].buildingTypeBasedEmployeeCount + > DAT_GameState::instance.playerDataArray[playerID].availablePeasantsAtFire + && (DAT_GameState::instance.playerDataArray[playerID].populationCap + <= DAT_GameState::instance.playerDataArray[playerID].currentPopulation + || DAT_GameState::instance.playerDataArray[playerID].popularity < 5000)) { + MACRO_CALL_MEMBER(OpenSHC::UI::BottomLeftTextDisplayState_Func::setBottomLeftTextDisplayText, + DAT_BottomLeftTextDisplayState::ptr)(1, 0x4d, 1, 0, 100, 6000); + } + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/placeWorkshopOrHovel.cpp b/src/OpenSHC/Map/TileMapState/placeWorkshopOrHovel.cpp new file mode 100644 index 0000000000..98209d9ab2 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/placeWorkshopOrHovel.cpp @@ -0,0 +1,62 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Map/Buildings/BuildingsState.func.hpp" +#include "OpenSHC/UI/BottomLeftTextDisplayState.func.hpp" + +#include "OpenSHC/Globals/DAT_BottomLeftTextDisplayState.hpp" +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_GameState.hpp" +#include "OpenSHC/Globals/DAT_GameSynchronyState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_BUILDING; + + // FUNCTION: STRONGHOLDCRUSADER 0x00506BD0 + void TileMapState::placeWorkshopOrHovel( + int playerID, uint x, uint y, BuildingType type, uint size, int orientation, undefined4 averageHeight) + { + int tileIndex = 0; + int buildingID = MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::setupBuildingData, DAT_BuildingsState::ptr)( + playerID, x, y, averageHeight, (BuildingType)(short)type, size, playerID, orientation); + /* the original stores only the low half of the int field */ + *(short*)&DAT_BuildingsState::instance.buildings[buildingID].hovelVisualStyle + = (short)DAT_GameState::instance.playerDataArray[playerID].hovelCountUpToEight; + if ((short)type == OpenSHC::Map::Buildings::BT_HOVEL) { + DAT_GameState::instance.playerDataArray[playerID].hovelCountUpToEight + = (DAT_GameState::instance.playerDataArray[playerID].hovelCountUpToEight + 1) % 7; + } + this->placedBuildingID = buildingID; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)(tileIndex, size); + int tileUnk = DAT_ViewportRenderState::instance.translationMatrix[this->buildingY + y].addXgetTile + + this->buildingX + x; + if (tileIndex < 36) { + DAT_BuildingsState::instance.buildings[buildingID].tileRefs[tileIndex] = tileUnk; + } + this->HeightLayer[tileUnk] = (byte)averageHeight; + this->LogicLayer[tileUnk] = this->LogicLayer[tileUnk] | L_BUILDING; + this->BuildingLayer[tileUnk] = (short)buildingID; + tileIndex++; + this->BuildingWasLayer[tileUnk] = (uchar)type; + this->ChangedLayer[tileUnk] = 2; + } while (tileIndex < this->constructionTileCount); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::setMiscDisplayLayer, this)(buildingID); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::updatePathLinkagesForBuilding, this)(buildingID); + if (playerID == DAT_GameSynchronyState::instance.currentPlayerSlotID + && (int)DAT_BuildingsState::instance.buildings[buildingID].buildingTypeBasedEmployeeCount + > DAT_GameState::instance.playerDataArray[playerID].availablePeasantsAtFire + && (DAT_GameState::instance.playerDataArray[playerID].populationCap + <= DAT_GameState::instance.playerDataArray[playerID].currentPopulation + || DAT_GameState::instance.playerDataArray[playerID].popularity < 5000)) { + MACRO_CALL_MEMBER(OpenSHC::UI::BottomLeftTextDisplayState_Func::setBottomLeftTextDisplayText, + DAT_BottomLeftTextDisplayState::ptr)( + 1, 0x4d, 1, 0, 100, 6000); + } + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/planMoat.cpp b/src/OpenSHC/Map/TileMapState/planMoat.cpp new file mode 100644 index 0000000000..6734ace63a --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/planMoat.cpp @@ -0,0 +1,62 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" + +#include "OpenSHC/Globals/DAT_PathFindingState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_BORDER; + using OpenSHC::Map::LogicHelpers::L_BORDER_EDGE; + using OpenSHC::Map::LogicHelpers::L_BOULDERS; + using OpenSHC::Map::LogicHelpers::L_BUILDING; + using OpenSHC::Map::LogicHelpers::L_FORD; + using OpenSHC::Map::LogicHelpers::L_IRON; + using OpenSHC::Map::LogicHelpers::L_KEEP_NON_MANOR_HOUSE; + using OpenSHC::Map::LogicHelpers::L_MARSH; + using OpenSHC::Map::LogicHelpers::L_MOAT; + using OpenSHC::Map::LogicHelpers::L_MOAT_DUG_OR_PLANNED; + using OpenSHC::Map::LogicHelpers::L_PLAIN1_AND_FARM; + using OpenSHC::Map::LogicHelpers::L_RIVER; + using OpenSHC::Map::LogicHelpers::L_ROCKY; + using OpenSHC::Map::LogicHelpers::L_SEA; + using OpenSHC::Map::LogicHelpers::L_WALL_OR_GATEHOUSE; + + // FUNCTION: STRONGHOLDCRUSADER 0x00514480 + void TileMapState::planMoat(undefined4 playerID, int tile, uint tileY) + { + uint logic = this->LogicLayer[tile]; + if ((logic & (L_BORDER | L_BORDER_EDGE)) != 0) { + return; + } + if (this->OrganismLayer[tile] != 0) { + return; + } + if ((logic & (L_BUILDING | L_KEEP_NON_MANOR_HOUSE)) != 0) { + return; + } + if (this->BuildingLayer[tile] != 0) { + return; + } + if ((logic & (L_WALL_OR_GATEHOUSE | L_BOULDERS | L_IRON | L_RIVER | L_FORD | L_MARSH)) != 0) { + return; + } + if ((logic & (L_SEA | L_PLAIN1_AND_FARM | L_ROCKY)) != 0) { + return; + } + + int moatX = tile - DAT_ViewportRenderState::instance.translationMatrix[tileY].addXgetTile; + if ((logic & (L_MOAT_DUG_OR_PLANNED | L_MOAT)) == 0 && this->HeightLayer[tile] <= 12) { + if (MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::createMoatData, this)(playerID, moatX, tileY, 0) + != 0) { + this->LogicLayer[tile] = this->LogicLayer[tile] | L_MOAT_DUG_OR_PLANNED; + } + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::updatePathLinkagesInAllEightDirections, + DAT_PathFindingState::ptr)(tileY, tile); + } + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/prepareAreaForBuildingPlacement.cpp b/src/OpenSHC/Map/TileMapState/prepareAreaForBuildingPlacement.cpp new file mode 100644 index 0000000000..11951fe49d --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/prepareAreaForBuildingPlacement.cpp @@ -0,0 +1,122 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Game/GameStateStructures.func.hpp" +#include "OpenSHC/IO/LowLevelMemory.func.hpp" +#include "OpenSHC/Map/Buildings/BuildingsState.func.hpp" +#include "OpenSHC/Commands/MappersEnum.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" +#include "OpenSHC/Globals/DAT_LowLevelMemory.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_BORDER; + using OpenSHC::Map::LogicHelpers::L_BORDER_EDGE; + using OpenSHC::Map::LogicHelpers::L_FARM_FIELD_APPLE; + + using OpenSHC::Map::LogicHelpers::L_BORDER; + using OpenSHC::Map::LogicHelpers::L_BORDER_EDGE; + using OpenSHC::Map::LogicHelpers::L_FARM_FIELD_APPLE; + + using OpenSHC::Commands::MappersEnum; + using OpenSHC::Map::Buildings::BuildingType; + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x005160C0 + BOOLEnum TileMapState::prepareAreaForBuildingPlacement( + int playerID, uint x, uint y, MappersEnum commandBuildingType, int buildingWidthOrHeight) + { + BOOLEnum result = FALSE; + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::storeMinAndMaxHeightOfArea, this)( + x, y, buildingWidthOrHeight); + + int index = 0; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)( + index, buildingWidthOrHeight); + uint tileY = y + this->buildingY; + if (x + this->buildingX > 399 || tileY > 399) { + return FALSE; + } + if (DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[tileY * 400 + x + this->buildingX] == 0) { + return FALSE; + } + int tile = DAT_ViewportRenderState::instance.translationMatrix[tileY].addXgetTile + this->buildingX + x; + if ((this->LogicLayer[tile] & (L_BORDER | L_BORDER_EDGE)) != 0) { + return FALSE; + } + if (MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::isBuildingPlacementAllowedAtTile, this)( + tile, playerID, (MappersEnum)(short)commandBuildingType, 1) + == 1) { + return FALSE; + } + index++; + } while (index < this->constructionTileCount); + + /* the original walks the footprint again through the command parameter */ + commandBuildingType = OpenSHC::Commands::M_MAPPER_NULL; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)( + commandBuildingType, buildingWidthOrHeight); + int tile = DAT_ViewportRenderState::instance.translationMatrix[this->buildingY + y].addXgetTile + x + + this->buildingX; + int buildingID = DAT_TileMapState::instance.BuildingLayer[tile]; + bool cleared = false; + if (buildingID != 0) { + if (DAT_BuildingsState::instance.buildings[buildingID].buildingType + == OpenSHC::Map::Buildings::BT_WOODCUTTERSHUT + || DAT_BuildingsState::instance.buildings[buildingID].buildingType + == OpenSHC::Map::Buildings::BT_OXTETHER + || DAT_BuildingsState::instance.buildings[buildingID].buildingType + == OpenSHC::Map::Buildings::BT_QUARRY + || DAT_BuildingsState::instance.buildings[buildingID].buildingType + == OpenSHC::Map::Buildings::BT_IRONMINE + || DAT_BuildingsState::instance.buildings[buildingID].buildingType + == OpenSHC::Map::Buildings::BT_WHEATFARM + || DAT_BuildingsState::instance.buildings[buildingID].buildingType + == OpenSHC::Map::Buildings::BT_HOPFARM + || DAT_BuildingsState::instance.buildings[buildingID].buildingType + == OpenSHC::Map::Buildings::BT_APPLEFARM + || DAT_BuildingsState::instance.buildings[buildingID].buildingType + == OpenSHC::Map::Buildings::BT_DAIRYFARM) { + MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::giveBackResourceForDestroyedBuilding, + DAT_BuildingsState::ptr)(buildingID, playerID, 50); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::clearBuildingFromTerrain, this)(buildingID); + MACRO_CALL_MEMBER( + OpenSHC::Game::GameStateStructures_Func::updatePrimaryBuildingPlayerDataReferences, + DAT_GameState::ptr)(buildingID); + cleared = true; + } + } else if ((DAT_TileMapState::instance.LogicLayer[tile] & L_FARM_FIELD_APPLE) != 0) { + buildingID = MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::getFarmThatHasTile, DAT_BuildingsState::ptr)(tile); + if (buildingID != 0) { + MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::giveBackResourceForDestroyedBuilding, + DAT_BuildingsState::ptr)(buildingID, playerID, 0x32); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::clearBuildingFromTerrain, this)(buildingID); + MACRO_CALL_MEMBER( + OpenSHC::Game::GameStateStructures_Func::updatePrimaryBuildingPlayerDataReferences, + DAT_GameState::ptr)(buildingID); + cleared = true; + } + } + if (cleared) { + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 0x32c, '\0', DAT_BuildingsState::instance.buildings + buildingID); + result = TRUE; + } + commandBuildingType = (MappersEnum)(commandBuildingType + OpenSHC::Commands::M_MAPPER_AREA); + } while ((int)commandBuildingType < this->constructionTileCount); + return result; + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/prepareMap.cpp b/src/OpenSHC/Map/TileMapState/prepareMap.cpp new file mode 100644 index 0000000000..b595f2c6c4 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/prepareMap.cpp @@ -0,0 +1,188 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/AI/AIVState.func.hpp" +#include "OpenSHC/Game/GameStateStructures.func.hpp" +#include "OpenSHC/IO/LowLevelMemory.func.hpp" +#include "OpenSHC/Map.func.hpp" +#include "OpenSHC/Map/Buildings/BuildingsState.func.hpp" +#include "OpenSHC/Map/Entities/EntityState.func.hpp" +#include "OpenSHC/Map/LandscapeState.func.hpp" +#include "OpenSHC/Map/MapPropertiesState.func.hpp" +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" +#include "OpenSHC/Map/Units/TribesState.func.hpp" +#include "OpenSHC/Map/Units/TroopValueState.func.hpp" +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Map/WildlifeState.func.hpp" +#include "OpenSHC/Rendering/ViewportRenderState.func.hpp" +#include "OpenSHC/Text/UserTextHandler.func.hpp" +#include "OpenSHC/UI/HoveredState.func.hpp" +#include "OpenSHC/UI/MinimapViewState.func.hpp" +#include "OpenSHC/Game/GameMode.hpp" +#include "OpenSHC/Game/GameMode2.hpp" +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +#include "OpenSHC/Globals/DAT_AIVState.hpp" +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_EntityState.hpp" +#include "OpenSHC/Globals/DAT_GameCore.hpp" +#include "OpenSHC/Globals/DAT_GameState.hpp" +#include "OpenSHC/Globals/DAT_GameSynchronyState.hpp" +#include "OpenSHC/Globals/DAT_HoveredState.hpp" +#include "OpenSHC/Globals/DAT_LandscapeState.hpp" +#include "OpenSHC/Globals/DAT_LowLevelMemory.hpp" +#include "OpenSHC/Globals/DAT_MapPropertiesState.hpp" +#include "OpenSHC/Globals/DAT_MinimapViewState.hpp" +#include "OpenSHC/Globals/DAT_PathFindingState.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_TribesState.hpp" +#include "OpenSHC/Globals/DAT_TroopValueState.hpp" +#include "OpenSHC/Globals/DAT_UnitsState.hpp" +#include "OpenSHC/Globals/DAT_UserTextHandlerState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" +#include "OpenSHC/Globals/DAT_WallAndPitchState.hpp" +#include "OpenSHC/Globals/DAT_WildlifeState.hpp" +#include "OpenSHC/Globals/FilePackagerObj.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Game::GameMode; + using OpenSHC::Game::GameMode2; + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x00512450 + void TileMapState::prepareMap() + { + int savedY = DAT_ViewportRenderState::instance.viewportState.viewportY; + int savedX = DAT_ViewportRenderState::instance.viewportState.viewportX; + if (DAT_GameSynchronyState::instance.currentGameModeCopy_SEC_Section1106 + == OpenSHC::Game::GM_SKIRMISH_SINGLE_PLAYER) { + DAT_GameSynchronyState::instance.currentGameMode = OpenSHC::Game::GM_SKIRMISH_SINGLE_PLAYER; + DAT_GameSynchronyState::instance.isHost = TRUE; + char* name = MACRO_CALL_MEMBER( + OpenSHC::Text::UserTextHandler_Func::getTextArrayPointer, DAT_UserTextHandlerState::ptr)(0); + /* the human player's name goes into slot 1, terminator included */ + int i = 0; + do { + DAT_GameSynchronyState::instance.DAT_PlayerNames[1][i] = name[i]; + i++; + } while (name[i - 1] != '\0'); + MACRO_CALL_MEMBER(OpenSHC::AI::AIVState_Func::syncAIPlayerNamesAndBuildIntervals, DAT_AIVState::ptr)(); + DAT_GameSynchronyState::instance.currentPlayerSlotID = 1; + } else if (DAT_GameCore::instance.gameMode_2 == OpenSHC::Game::GM_CAMPAIGN_MISSION) { + if (DAT_GameCore::instance.missionNumber1to20 < 16) { + DAT_GameSynchronyState::instance.currentGameMode = OpenSHC::Game::GM_SOLITARY; + } + } else if (DAT_GameCore::instance.gameMode_2 == OpenSHC::Game::GM_BUILDERUnk) { + DAT_GameSynchronyState::instance.currentGameMode = OpenSHC::Game::GM_SOLITARY; + } + + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::changeMapOrientation, this)(this->mapOrientation); + DAT_PathFindingState::instance.searchGeneration = 1; + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 0x27420, '\0', DAT_TileMapState::instance.WalkLayer); + DAT_ViewportRenderState::instance.viewportState.viewportX = savedX; + DAT_ViewportRenderState::instance.viewportState.viewportY = savedY; + MACRO_CALL_MEMBER( + OpenSHC::Rendering::ViewportRenderState_Func::setViewportBasedOnMapSize, DAT_ViewportRenderState::ptr)(); + MACRO_CALL_MEMBER(OpenSHC::Rendering::ViewportRenderState_Func::setTileSystemMemoryLookupArrays, + DAT_ViewportRenderState::ptr)(); + MACRO_CALL_MEMBER(OpenSHC::Rendering::ViewportRenderState_Func::tweakValidTilesToExcludeMapBorders, + DAT_ViewportRenderState::ptr)(); + DAT_BuildingsState::instance.maxBuildingsCount = 2000; + DAT_UnitsState::instance.maxUnitCount = 2500; + DAT_PathFindingState::instance.maxClimbDataCount = 200; + DAT_EntityState::instance.maxEntityCount = 3000; + this->currentMoatCount = 16000; + DAT_LandscapeState::instance.maxTreeCount = 2000; + this->maxPitchDitchCount = 4000; + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::resetHeightAndMapBorders, this)(this->mapSize); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::toggleFlatView, this)(0); + DAT_TileMapState::instance.field95_0x5548d0 = 0; + DAT_TileMapState::instance.flatViewToggleValue2 = 0; + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::setChangedLayerToThreeAndMapping0x40x40, this)(); + this->forceUpdateLogicalAndMiscDisplayLayers = 1; + this->forceUpdateTextureTilemap = 1; + this->forceUpdateGFXLayers = 1; + this->forceUpdateMacroLayerFlag = 1; + this->field68_0x55487c = 500; + + /* every subsystem gets a chance to migrate what it loaded from an older map format */ + MACRO_CALL_MEMBER(OpenSHC::Map::Units::TribesState_Func::upgradeTribeArrayLayoutForMapVersion, + DAT_TribesState::ptr)((PackagedFileMagicNum)(int)FilePackagerObj::instance.versionNumOfCurrentFileTypeUnk, + (PackagedFileMagicNum)(int)FilePackagerObj::instance.packagerMapVersionNumUnk); + MACRO_CALL_MEMBER(OpenSHC::Map::Units::TroopValueState_Func::uselessFunction, DAT_TroopValueState::ptr)( + (PackagedFileMagicNum)(int)FilePackagerObj::instance.versionNumOfCurrentFileTypeUnk, + (PackagedFileMagicNum)(int)FilePackagerObj::instance.packagerMapVersionNumUnk); + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::upgradeMapFormatForUnits, DAT_UnitsState::ptr)( + (PackagedFileMagicNum)(int)FilePackagerObj::instance.versionNumOfCurrentFileTypeUnk, + (PackagedFileMagicNum)(int)FilePackagerObj::instance.packagerMapVersionNumUnk); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::upgradeMapFormatLogicLayer, this)( + (PackagedFileMagicNum)(int)FilePackagerObj::instance.versionNumOfCurrentFileTypeUnk, + (PackagedFileMagicNum)(int)FilePackagerObj::instance.packagerMapVersionNumUnk); + MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::upgradeBuildingsForMapVersion, DAT_BuildingsState::ptr)( + (PackagedFileMagicNum)(int)FilePackagerObj::instance.versionNumOfCurrentFileTypeUnk, + (PackagedFileMagicNum)(int)FilePackagerObj::instance.packagerMapVersionNumUnk); + MACRO_CALL_MEMBER( + OpenSHC::Map::LandscapeState_Func::upgradeTreesAndRocksForMapVersion, DAT_LandscapeState::ptr)( + (PackagedFileMagicNum)(int)FilePackagerObj::instance.versionNumOfCurrentFileTypeUnk, + (PackagedFileMagicNum)(int)FilePackagerObj::instance.packagerMapVersionNumUnk); + MACRO_CALL_MEMBER(OpenSHC::Map::Units::TribesState_Func::upgradeMapTribesState, DAT_TribesState::ptr)( + (PackagedFileMagicNum)(int)FilePackagerObj::instance.versionNumOfCurrentFileTypeUnk, + (PackagedFileMagicNum)(int)FilePackagerObj::instance.packagerMapVersionNumUnk); + MACRO_CALL_MEMBER(OpenSHC::Game::GameStateStructures_Func::migrateGameStateForMapVersion, DAT_GameState::ptr)( + (PackagedFileMagicNum)(int)FilePackagerObj::instance.versionNumOfCurrentFileTypeUnk, + (PackagedFileMagicNum)(int)FilePackagerObj::instance.packagerMapVersionNumUnk); + MACRO_CALL_MEMBER(OpenSHC::Map::Entities::EntityState_Func::handleMapVersionUpgrade, DAT_EntityState::ptr)( + (PackagedFileMagicNum)(int)FilePackagerObj::instance.versionNumOfCurrentFileTypeUnk, + (PackagedFileMagicNum)(int)FilePackagerObj::instance.packagerMapVersionNumUnk); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::recountTotalOwnedMoats, this)(); + MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::PathFindingState_Func::updatePathLinkageLayerForEachBuildingAtEachTile, + DAT_PathFindingState::ptr)(); + MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::PathFindingState_Func::updateSeparateAreaTileMap, DAT_PathFindingState::ptr)(1); + MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::updatePathLinkageLayerForAllBuildings, + DAT_BuildingsState::ptr)(); + MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::PathFindingState_Func::updateClimbData, DAT_PathFindingState::ptr)(); + MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::clearBuildingValueWhenStateIsTwo, DAT_BuildingsState::ptr)(); + MACRO_CALL_MEMBER(OpenSHC::Map::LandscapeState_Func::setCurrentTimeOnSomeTrees, DAT_LandscapeState::ptr)(); + MACRO_CALL_MEMBER(OpenSHC::Map::LandscapeState_Func::resetWind, DAT_LandscapeState::ptr)(); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::collectCliffEdgeTilesForClimbData, this)(); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::clearInvalidMoatEntries, this)(); + MACRO_CALL_MEMBER( + OpenSHC::Game::GameStateStructures_Func::initializeGameStateAfterMapLoad, DAT_GameState::ptr)(); + MACRO_CALL_MEMBER(OpenSHC::Map::MapPropertiesState_Func::sortEventsByDate, DAT_MapPropertiesState::ptr)(); + MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::applyVersionUpgradeAccessibilityRecompute, + DAT_BuildingsState::ptr)( + (PackagedFileMagicNum)(int)FilePackagerObj::instance.versionNumOfCurrentFileTypeUnk, + (PackagedFileMagicNum)(int)FilePackagerObj::instance.packagerMapVersionNumUnk); + MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::PathFindingState_Func::updateSeparateAreaTileMap, DAT_PathFindingState::ptr)(1); + MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::updatePathLinkageLayerForAllBuildings, + DAT_BuildingsState::ptr)(); + + for (int grid = 0; grid < 40; grid++) { + MACRO_CALL_MEMBER(OpenSHC::Map::WildlifeState_Func::updateWildlifeGrid, DAT_WildlifeState::ptr)(grid); + } + MACRO_CALL_MEMBER(OpenSHC::Map::WildlifeState_Func::updateWildlife, DAT_WildlifeState::ptr)(); + MACRO_CALL_MEMBER(OpenSHC::Map::WildlifeState_Func::updateSection1034Info, DAT_WildlifeState::ptr)(); + MACRO_CALL_MEMBER(OpenSHC::Map::WildlifeState_Func::updateNofFpoints, DAT_WildlifeState::ptr)(); + MACRO_CALL(OpenSHC::Map_Func::ResetSomeValuesFunctionUnk)(); + DAT_WallAndPitchState::instance.countdown = 0; + MACRO_CALL_MEMBER(OpenSHC::UI::HoveredState_Func::clearHoveredState, DAT_HoveredState::ptr)(); + DAT_GameCore::instance.gamePausedLogical = 0xffffffff; + MACRO_CALL_MEMBER(OpenSHC::Game::GameStateStructures_Func::processGameTick, DAT_GameState::ptr)(); + MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::PathFindingState_Func::updateSeparateAreaTileMap, DAT_PathFindingState::ptr)(1); + MACRO_CALL_MEMBER( + OpenSHC::UI::MinimapViewState_Func::setTileColorsDependingOnMapSize, DAT_MinimapViewState::ptr)(0, 100); + MACRO_CALL_MEMBER( + OpenSHC::UI::MinimapViewState_Func::setMapPropertyDependingOnMapSize, DAT_MinimapViewState::ptr)(0, 100); + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/processDamageToBuilding.cpp b/src/OpenSHC/Map/TileMapState/processDamageToBuilding.cpp new file mode 100644 index 0000000000..bf81531623 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/processDamageToBuilding.cpp @@ -0,0 +1,532 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/AI/AICState.func.hpp" +#include "OpenSHC/Audio/MSS/SoundSystem.func.hpp" +#include "OpenSHC/Audio/SFX/SFXState.func.hpp" +#include "OpenSHC/Map/Buildings/BuildingsState.func.hpp" +#include "OpenSHC/Map/Entities.func.hpp" +#include "OpenSHC/Map/Entities/EntityState.func.hpp" +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Map/Version.func.hpp" +#include "OpenSHC/Random/RNG.func.hpp" +#include "OpenSHC/Commands/MappersEnum.hpp" +#include "OpenSHC/DE/SHCDE/eSFX.hpp" +#include "OpenSHC/Game/GameMode.hpp" +#include "OpenSHC/Map/Buildings/BuildingLogicalState.hpp" +#include "OpenSHC/Map/Buildings/BuildingType.hpp" +#include "OpenSHC/Map/Entities/EntityType.hpp" +#include "OpenSHC/Map/Units/States/UnitState.hpp" +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +#include "OpenSHC/Globals/DAT_AICState.hpp" +#include "OpenSHC/Globals/DAT_BuildingDefinedData.hpp" +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_EntityState.hpp" +#include "OpenSHC/Globals/DAT_GameCore.hpp" +#include "OpenSHC/Globals/DAT_GameState.hpp" +#include "OpenSHC/Globals/DAT_GameSynchronyState.hpp" +#include "OpenSHC/Globals/DAT_PathFindingState.hpp" +#include "OpenSHC/Globals/DAT_SFXState.hpp" +#include "OpenSHC/Globals/DAT_SoundSystemState.hpp" +#include "OpenSHC/Globals/DAT_TroopValueState.hpp" +#include "OpenSHC/Globals/DAT_UnitsState.hpp" +#include "OpenSHC/Globals/SEC_RNG.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_BUILDING; + using OpenSHC::Map::LogicHelpers::L_CRENEL; + using OpenSHC::Map::LogicHelpers::L_CRENEL_VARIATIONUnk; + using OpenSHC::Map::LogicHelpers::L_KEEP_NON_MANOR_HOUSE; + using OpenSHC::Map::LogicHelpers::L_STAIRS; + using OpenSHC::Map::LogicHelpers::L_STOCKPILEUnk; + using OpenSHC::Map::LogicHelpers::L_UNKNOWN_WALL_RELATED; + using OpenSHC::Map::LogicHelpers::L_WALL_OR_GATEHOUSE; + + using OpenSHC::Commands::MappersEnum; + using OpenSHC::DE::SHCDE::eSFX; + using OpenSHC::Game::GameMode; + using OpenSHC::Map::Buildings::BuildingLogicalState; + using OpenSHC::Map::Buildings::BuildingType; + using OpenSHC::Map::Entities::EntityType; + using OpenSHC::Map::Units::States::UnitState; + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x00516B80 + BOOLEnum TileMapState::processDamageToBuilding(int tile, uint xPosition, uint yPosition, int damageUnk, int param_5, + int playerID, BOOLEnum aiBuildDelayRelated, int unitID) + { + BOOLEnum destroyed = FALSE; + byte replaced = 0; + /* a negative player id is a request to spare that player's own team */ + bool spareOwnTeam = false; + if (playerID < 0) { + playerID = -playerID; + if (DAT_GameSynchronyState::instance.currentPlayerFullIDArray[playerID] == -1) { + spareOwnTeam = true; + } + } + + uint logic = this->LogicLayer[tile]; + if ((logic & (L_BUILDING | L_KEEP_NON_MANOR_HOUSE)) == 0 && this->BuildingLayer[tile] == 0) { + if ((logic & L_WALL_OR_GATEHOUSE) == 0) { + destroyed = TRUE; + } else { + if ((logic & L_STOCKPILEUnk) != 0) { + return FALSE; + } + uint wallOwner = this->WallOwnerLayer[tile] & 7; + if (spareOwnTeam + && DAT_GameState::instance.mapAndTime.playerTeams[playerID] + == DAT_GameState::instance.mapAndTime.playerTeams[wallOwner + 1]) { + return FALSE; + } + DAT_GameState::instance.playerDataArray[wallOwner + 1].defensesDamagedByPlayer = (short)playerID; + if (unitID != 0) { + if (DAT_GameState::instance.mapAndTime.playerTeams[wallOwner + 1] + == DAT_GameState::instance.mapAndTime.playerTeams[playerID]) { + DAT_UnitsState::instance.units[unitID].friendlyFireCounterUnk + = DAT_UnitsState::instance.units[unitID].friendlyFireCounterUnk + 1; + } else { + DAT_UnitsState::instance.units[unitID].friendlyFireCounterUnk = 0; + } + } + /* a wall standing alone takes half again the damage, a well connected one half */ + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::countLogicPropertyInSurroundingTiles, this)( + tile, yPosition, L_KEEP_NON_MANOR_HOUSE | L_WALL_OR_GATEHOUSE); + if (this->DAT_CardinalTilesAroundTile < 2) { + damageUnk = damageUnk + damageUnk / 2; + } else if (this->DAT_CardinalTilesAroundTile > 2) { + damageUnk = damageUnk / 2; + } + if (param_5 != 0) { + damageUnk = 0; + } + DAT_TroopValueState::instance.attackInfo.buildingDamageEventCount + = DAT_TroopValueState::instance.attackInfo.buildingDamageEventCount + 1; + DAT_GameCore::instance.cowPoisonTrackerUnk + = DAT_GameCore::instance.cowPoisonTrackerUnk + damageUnk * 10; + if (param_5 == 0 && (this->LogicLayer[tile] & L_UNKNOWN_WALL_RELATED) == 0 + && this->DamageLayer[tile] == 0 + && this->DefaultHeightLayer[tile] + 60 < (uint)this->HeightLayer[tile]) { + this->HeightLayer[tile] = this->HeightLayer[tile] - 20; + } + for (int hit = 0; hit < damageUnk; hit++) { + if (this->HeightLayer[tile] <= this->DefaultHeightLayer[tile]) { + MACRO_CALL_MEMBER(OpenSHC::Map::Entities::EntityState_Func::destroyEntitiesOnTile, + DAT_EntityState::ptr)(tile); + this->LogicLayer[tile] = this->LogicLayer[tile] + & ~(L_WALL_OR_GATEHOUSE | L_CRENEL | L_STAIRS | L_UNKNOWN_WALL_RELATED + | L_CRENEL_VARIATIONUnk); + this->HeightLayer[tile] = this->DefaultHeightLayer[tile]; + this->DamageLayer[tile] = 0; + DAT_PathFindingState::instance.toggleUpdateSeparateAreaTileMap = 1; + this->field204_0x554a30 = 1; + destroyed = TRUE; + break; + } + this->HeightLayer[tile] = this->HeightLayer[tile] - 1; + if ((char)this->DamageLayer[tile] < 200) { + this->DamageLayer[tile] = this->DamageLayer[tile] + 1; + } + } + MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::PathFindingState_Func::updatePathLinkagesInAllEightDirections, + DAT_PathFindingState::ptr)(yPosition, tile); + } + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::updateWalkAndPathLayer, + DAT_PathFindingState::ptr)(7, xPosition, yPosition); + return ~-(uint)replaced & destroyed; + } + + int buildingID = this->BuildingLayer[tile]; + if (DAT_BuildingsState::instance.buildings[buildingID].logicalState == (BuildingLogicalState)0 + || DAT_BuildingsState::instance.buildings[buildingID].logicalState == OpenSHC::Map::Buildings::BLS_REMOVE) { + return TRUE; + } + short health = DAT_BuildingsState::instance.buildings[buildingID].currentHealth; + if (health == 0) { + return TRUE; + } + DAT_GameCore::instance.cowPoisonTrackerUnk = DAT_GameCore::instance.cowPoisonTrackerUnk + damageUnk * 10; + if (DAT_BuildingDefinedData::instance + .BuildingTypeHasHealth[(short)DAT_BuildingsState::instance.buildings[buildingID].buildingType] + == 0) { + return TRUE; + } + if ((this->LogicLayer[tile] & 0xf000000) != 0) { + return TRUE; + } + if (spareOwnTeam + && DAT_GameState::instance.mapAndTime.playerTeams[playerID] + == DAT_GameState::instance.mapAndTime + .playerTeams[DAT_BuildingsState::instance.buildings[buildingID].owner]) { + return FALSE; + } + DAT_BuildingsState::instance.buildings[buildingID].currentHealth = health - (short)damageUnk; + + if (aiBuildDelayRelated == TRUE + && (DAT_BuildingsState::instance.buildings[buildingID].buildingType + == OpenSHC::Map::Buildings::BT_GATEHOUSELARGE + || DAT_BuildingsState::instance.buildings[buildingID].buildingType + == OpenSHC::Map::Buildings::BT_GATEHOUSESMALL)) { + /* a damaged gatehouse loses its drawbridges straight away */ + int bridge = MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::findParticularBuilding, + DAT_BuildingsState::ptr)(DAT_BuildingsState::instance.buildings[buildingID].owner, + (short)DAT_BuildingsState::instance.buildings[buildingID].x, + (short)DAT_BuildingsState::instance.buildings[buildingID].y, + DAT_BuildingsState::instance.buildings[buildingID].widthOrHeight, + OpenSHC::Map::Buildings::BT_DRAWBRIDGE, 0); + if (bridge != 0) { + this->showNoRubbleWhenDestroyingBuilding + = DAT_BuildingDefinedData::instance.BuildingShowRubbleWhenDestroyed + [(short)DAT_BuildingsState::instance.buildings[bridge].buildingType] + == 0; + MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::destroyBuilding, DAT_BuildingsState::ptr)(bridge); + int second = MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::findParticularBuilding, + DAT_BuildingsState::ptr)(DAT_BuildingsState::instance.buildings[buildingID].owner, + (short)DAT_BuildingsState::instance.buildings[buildingID].x, + (short)DAT_BuildingsState::instance.buildings[buildingID].y, + DAT_BuildingsState::instance.buildings[buildingID].widthOrHeight, + OpenSHC::Map::Buildings::BT_DRAWBRIDGE, bridge); + if (second != 0) { + this->showNoRubbleWhenDestroyingBuilding + = DAT_BuildingDefinedData::instance.BuildingShowRubbleWhenDestroyed + [(short)DAT_BuildingsState::instance.buildings[second].buildingType] + == 0; + MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::destroyBuilding, DAT_BuildingsState::ptr)(second); + } + } + } + + switch (DAT_BuildingsState::instance.buildings[buildingID].buildingType) { + case OpenSHC::Map::Buildings::BT_GATEHOUSELARGE: + case OpenSHC::Map::Buildings::BT_GATEHOUSESMALL: + case OpenSHC::Map::Buildings::BT_TOWER1: + case OpenSHC::Map::Buildings::BT_TOWER2: + case OpenSHC::Map::Buildings::BT_TOWER3: + case OpenSHC::Map::Buildings::BT_TOWER4: + case OpenSHC::Map::Buildings::BT_TOWER5: + DAT_GameState::instance.playerDataArray[DAT_BuildingsState::instance.buildings[buildingID].owner] + .defensesDamagedByPlayer = (short)playerID; + break; + default: + break; + } + if (unitID != 0) { + if (DAT_GameState::instance.mapAndTime.playerTeams[DAT_BuildingsState::instance.buildings[buildingID].owner] + == DAT_GameState::instance.mapAndTime.playerTeams[playerID]) { + DAT_UnitsState::instance.units[unitID].friendlyFireCounterUnk + = DAT_UnitsState::instance.units[unitID].friendlyFireCounterUnk + 1; + } else { + DAT_UnitsState::instance.units[unitID].friendlyFireCounterUnk = 0; + } + } + + short remaining = DAT_BuildingsState::instance.buildings[buildingID].currentHealth; + if (remaining > 0) { + /* a siege tower's rider takes the damage with it */ + if (DAT_BuildingsState::instance.buildings[buildingID].buildingType + == OpenSHC::Map::Buildings::BT_SIEGETOWER_PLACED + && DAT_BuildingsState::instance.buildings[buildingID].unitRefID != 0 + && DAT_BuildingsState::instance.buildings[buildingID].unitRefUID + == DAT_UnitsState::instance.units[DAT_BuildingsState::instance.buildings[buildingID].unitRefID].uid + && DAT_BuildingsState::instance.buildings[buildingID].maxHealth != 0) { + DAT_UnitsState::instance.units[DAT_BuildingsState::instance.buildings[buildingID].unitRefID].health + = ((int)remaining + * DAT_UnitsState::instance.units[DAT_BuildingsState::instance.buildings[buildingID].unitRefID] + .maxHealth) + / (int)DAT_BuildingsState::instance.buildings[buildingID].maxHealth; + } + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::updateWalkAndPathLayer, + DAT_PathFindingState::ptr)(7, xPosition, yPosition); + return ~-(uint)replaced & destroyed; + } + + if (DAT_BuildingsState::instance.buildings[buildingID].owner + == DAT_GameSynchronyState::instance.currentPlayerSlotID) { + MACRO_CALL(OpenSHC::Map::Version_Func::UpdateDestroyedBuildingCountData)(1); + } + int owner = DAT_BuildingsState::instance.buildings[buildingID].owner; + if (aiBuildDelayRelated == TRUE && DAT_GameState::instance.playerDataArray[owner].resourceRebuildDelay == 0) { + DAT_GameState::instance.playerDataArray[owner].resourceRebuildDelay = 1; + } + int destroyedType = (short)DAT_BuildingsState::instance.buildings[buildingID].buildingType; + if (destroyedType != OpenSHC::Map::Buildings::BT_UNKNOWN3 && (destroyedType < 0x56 || destroyedType > 0x59)) { + DAT_GameSynchronyState::instance.finalResults.finalBuildingsBurned[playerID] + = DAT_GameSynchronyState::instance.finalResults.finalBuildingsBurned[playerID] + 1; + DAT_GameSynchronyState::instance.finalResults.finalBuildingsDestroyedWeighted[playerID] + = DAT_GameSynchronyState::instance.finalResults.finalBuildingsDestroyedWeighted[playerID] + + DAT_BuildingDefinedData::instance.BuildingDestroyedScoreWeight[destroyedType]; + DAT_GameSynchronyState::instance.finalResults.finalBuidingsDestroyed[owner] + = DAT_GameSynchronyState::instance.finalResults.finalBuidingsDestroyed[owner] + 1; + /* a per-attacker tally inside the owner's player data, 0x20 apart */ + int* tally = (int*)((char*)&DAT_GameState::instance.playerDataArray[owner].attackedByPlayerArrayUnk[0][1] + + playerID * 0x20); + *tally = *tally + 1; + } + switch (DAT_BuildingsState::instance.buildings[buildingID].buildingType) { + case OpenSHC::Map::Buildings::BT_OILSMELTER: + case OpenSHC::Map::Buildings::BT_GATEHOUSELARGE: + case OpenSHC::Map::Buildings::BT_GATEHOUSESMALL: + case OpenSHC::Map::Buildings::BT_TOWER1: + case OpenSHC::Map::Buildings::BT_TOWER2: + case OpenSHC::Map::Buildings::BT_TOWER3: + case OpenSHC::Map::Buildings::BT_TOWER4: + case OpenSHC::Map::Buildings::BT_TOWER5: + MACRO_CALL_MEMBER(OpenSHC::AI::AICState_Func::playAnger2BikFromPlayerToPlayer, DAT_AICState::ptr)( + owner, playerID); + break; + default: + MACRO_CALL_MEMBER(OpenSHC::AI::AICState_Func::playVictory2BikFromPlayerToPlayer, DAT_AICState::ptr)( + owner, playerID); + } + if (DAT_GameSynchronyState::instance.currentGameMode != OpenSHC::Game::GM_SOLITARY + && playerID == DAT_GameSynchronyState::instance.currentPlayerSlotID + && DAT_GameState::instance.mapAndTime.playerTeams[owner] + != DAT_GameState::instance.mapAndTime.playerTeams[DAT_GameSynchronyState::instance.currentPlayerSlotID] + && (DAT_BuildingsState::instance.buildings[buildingID].buildingType == OpenSHC::Map::Buildings::BT_TOWER4 + || DAT_BuildingsState::instance.buildings[buildingID].buildingType == OpenSHC::Map::Buildings::BT_TOWER5 + || DAT_BuildingsState::instance.buildings[buildingID].buildingType + == OpenSHC::Map::Buildings::BT_GATEHOUSELARGE + || DAT_BuildingsState::instance.buildings[buildingID].buildingType == OpenSHC::Map::Buildings::BT_CHURCH + || DAT_BuildingsState::instance.buildings[buildingID].buildingType + == OpenSHC::Map::Buildings::BT_CATHEDRAL) + && MACRO_CALL_MEMBER( + OpenSHC::Audio::MSS::SoundSystem_Func::shouldSoundXNotBePlaying, DAT_SoundSystemState::ptr)() + == FALSE) { + MACRO_CALL_MEMBER(OpenSHC::Random::RNG_Func::nextRandomNumber1, SEC_RNG::ptr)(); + if (DAT_GameCore::instance.genieVoiceActive != FALSE) { + /* "Watch it crumble" */ + MACRO_CALL_MEMBER(OpenSHC::Audio::SFX::SFXState_Func::playWAVSFX, DAT_SFXState::ptr)("Genie_36.wav"); + } + } + + bool destroyNormally = false; + int towerX = 0; + int towerY = 0; + int towerOwner = 0; + int towerSize = 0; + MappersEnum towerCommand = OpenSHC::Commands::M_MAPPER_NULL; + switch (DAT_BuildingsState::instance.buildings[buildingID].buildingType) { + case OpenSHC::Map::Buildings::BT_OILSMELTER: + if (DAT_BuildingsState::instance.buildings[buildingID].resources[7] == 0) { + destroyNormally = true; + break; + } + { + /* a smelter with oil in it goes up, and a full one throws burning oil about */ + int oilAmount = DAT_BuildingsState::instance.buildings[buildingID].resources[7]; + int smelterX = (short)DAT_BuildingsState::instance.buildings[buildingID].x; + int smelterOwner = DAT_BuildingsState::instance.buildings[buildingID].owner; + uint smelterTile = DAT_BuildingsState::instance.buildings[buildingID].currentTilePositionAdjusted; + DAT_BuildingsState::instance.buildings[buildingID].noRubble = 0; + int smelterY = (short)DAT_BuildingsState::instance.buildings[buildingID].y; + MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::deleteBuilding, DAT_BuildingsState::ptr)(buildingID); + if (oilAmount < 5) { + MACRO_CALL(OpenSHC::Map::Entities_Func::SetPlaceOnFire)( + smelterOwner, smelterX * 8 + 0x10, smelterY * 8 + 0x10, this->HeightLayer[smelterTile], 3); + } else { + MACRO_CALL(OpenSHC::Map::Entities_Func::SetPlaceOnFire)( + smelterOwner, smelterX * 8 + 0x10, smelterY * 8 + 0x10, this->HeightLayer[smelterTile], 5); + MACRO_CALL_MEMBER( + OpenSHC::Map::Entities::EntityState_Func::spawnProjectileEntity, DAT_EntityState::ptr)(0, + smelterOwner, 0, smelterX * 8 + 0x10, smelterY * 8 + 0x10, this->HeightLayer[smelterTile], 0, 0, + 0, OpenSHC::Map::Entities::EntityTypeInt__ET_EXPLOSION, 0); + } + MACRO_CALL_MEMBER(OpenSHC::Audio::SFX::SFXState_Func::playSFXAtLocation, DAT_SFXState::ptr)( + smelterX, smelterY, OpenSHC::DE::SHCDE::FX_IGNITE_PITCH); + destroyed = TRUE; + } + break; + case OpenSHC::Map::Buildings::BT_GATEHOUSELARGE: + case OpenSHC::Map::Buildings::BT_GATEHOUSESMALL: { + int bridge = MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::findParticularBuilding, + DAT_BuildingsState::ptr)(DAT_BuildingsState::instance.buildings[buildingID].owner, + (short)DAT_BuildingsState::instance.buildings[buildingID].x, + (short)DAT_BuildingsState::instance.buildings[buildingID].y, + DAT_BuildingsState::instance.buildings[buildingID].widthOrHeight, + OpenSHC::Map::Buildings::BT_DRAWBRIDGE, 0); + if (bridge != 0) { + this->showNoRubbleWhenDestroyingBuilding + = DAT_BuildingDefinedData::instance.BuildingShowRubbleWhenDestroyed + [(short)DAT_BuildingsState::instance.buildings[bridge].buildingType] + == 0; + MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::destroyBuilding, DAT_BuildingsState::ptr)(bridge); + int second = MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::findParticularBuilding, + DAT_BuildingsState::ptr)(DAT_BuildingsState::instance.buildings[buildingID].owner, + (short)DAT_BuildingsState::instance.buildings[buildingID].x, + (short)DAT_BuildingsState::instance.buildings[buildingID].y, + DAT_BuildingsState::instance.buildings[buildingID].widthOrHeight, + OpenSHC::Map::Buildings::BT_DRAWBRIDGE, bridge); + if (second != 0) { + this->showNoRubbleWhenDestroyingBuilding + = DAT_BuildingDefinedData::instance.BuildingShowRubbleWhenDestroyed + [(short)DAT_BuildingsState::instance.buildings[second].buildingType] + == 0; + MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::destroyBuilding, DAT_BuildingsState::ptr)(second); + } + } + ushort gateY = DAT_BuildingsState::instance.buildings[buildingID].y; + ushort gateX = DAT_BuildingsState::instance.buildings[buildingID].x; + MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::processDamageToUnitsOnBuilding, + DAT_BuildingsState::ptr)(buildingID, 50); + this->showNoRubbleWhenDestroyingBuilding + = DAT_BuildingDefinedData::instance.BuildingShowRubbleWhenDestroyed + [(short)DAT_BuildingsState::instance.buildings[buildingID].buildingType] + == 0; + MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::destroyBuilding, DAT_BuildingsState::ptr)( + buildingID); + MACRO_CALL_MEMBER(OpenSHC::Audio::SFX::SFXState_Func::playSFXAtLocation, DAT_SFXState::ptr)( + (short)gateX, (short)gateY, OpenSHC::DE::SHCDE::FX_TOWER_SMASH); + destroyed = TRUE; + } break; + case OpenSHC::Map::Buildings::BT_TUNNEL: { + /* the tunneller inside is buried where he stands */ + uint tunneller = DAT_BuildingsState::instance.buildings[buildingID].unitRefID; + if (DAT_UnitsState::instance.units[tunneller].state.generic + != (OpenSHC::Map::Units::States::US_STAND_UPUnk | OpenSHC::Map::Units::States::US_IDLEUnk)) { + DAT_UnitsState::instance.units[tunneller].totalSizeOfPathPlan + = DAT_UnitsState::instance.units[tunneller].currentIndexInPathPlan; + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::applyTunnelDamageAlongPathPlan, + DAT_UnitsState::ptr)(tunneller); + } + DAT_UnitsState::instance.units[tunneller].state.generic = OpenSHC::Map::Units::States::US_DISAPPEAR; + DAT_UnitsState::instance.units[tunneller].disappearFadeAlphaCountdown = 0x20; + DAT_UnitsState::instance.units[tunneller].updateTickTracker = 0x20; + } + destroyNormally = true; + break; + default: + destroyNormally = true; + break; + case OpenSHC::Map::Buildings::BT_SIEGETOWER_PLACED: { + int rider = DAT_BuildingsState::instance.buildings[buildingID].unitRefID; + if (rider != 0 + && DAT_BuildingsState::instance.buildings[buildingID].unitRefUID + == DAT_UnitsState::instance.units[rider].uid) { + DAT_UnitsState::instance.units[rider].state.generic = OpenSHC::Map::Units::States::US_DISAPPEAR; + DAT_UnitsState::instance.units[rider].disappearFadeAlphaCountdown = 0; + DAT_UnitsState::instance.units[rider].updateTickTracker = 0; + DAT_UnitsState::instance.units[rider].workplaceBuildingID_1 = 0; + } + DAT_BuildingsState::instance.buildings[buildingID].noRubble = 0; + MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::deleteBuilding, DAT_BuildingsState::ptr)( + buildingID); + destroyed = TRUE; + } break; + case OpenSHC::Map::Buildings::BT_TOWER1: + MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::processDamageToUnitsOnBuilding, + DAT_BuildingsState::ptr)(buildingID, 0x19); + towerOwner = DAT_BuildingsState::instance.buildings[buildingID].owner; + towerX = (short)DAT_BuildingsState::instance.buildings[buildingID].x; + DAT_BuildingsState::instance.buildings[buildingID].noRubble = 0; + towerY = (short)DAT_BuildingsState::instance.buildings[buildingID].y; + MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::deleteBuilding, DAT_BuildingsState::ptr)( + buildingID); + towerSize = 3; + towerCommand = OpenSHC::Commands::M_MAPPER_TOWER1_DESTROYED; + replaced = 1; + break; + case OpenSHC::Map::Buildings::BT_TOWER2: + MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::processDamageToUnitsOnBuilding, + DAT_BuildingsState::ptr)(buildingID, 0x32); + towerOwner = DAT_BuildingsState::instance.buildings[buildingID].owner; + towerX = (short)DAT_BuildingsState::instance.buildings[buildingID].x; + DAT_BuildingsState::instance.buildings[buildingID].noRubble = 0; + towerY = (short)DAT_BuildingsState::instance.buildings[buildingID].y; + MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::deleteBuilding, DAT_BuildingsState::ptr)( + buildingID); + towerSize = 4; + towerCommand = OpenSHC::Commands::M_MAPPER_TOWER2_DESTROYED; + replaced = 1; + break; + case OpenSHC::Map::Buildings::BT_TOWER3: + MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::processDamageToUnitsOnBuilding, + DAT_BuildingsState::ptr)(buildingID, 0x32); + towerOwner = DAT_BuildingsState::instance.buildings[buildingID].owner; + towerX = (short)DAT_BuildingsState::instance.buildings[buildingID].x; + DAT_BuildingsState::instance.buildings[buildingID].noRubble = 0; + towerY = (short)DAT_BuildingsState::instance.buildings[buildingID].y; + MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::deleteBuilding, DAT_BuildingsState::ptr)( + buildingID); + towerSize = 5; + towerCommand = OpenSHC::Commands::M_MAPPER_TOWER3_DESTROYED; + replaced = 1; + break; + case OpenSHC::Map::Buildings::BT_TOWER4: + MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::processDamageToUnitsOnBuilding, + DAT_BuildingsState::ptr)(buildingID, 0x32); + towerOwner = DAT_BuildingsState::instance.buildings[buildingID].owner; + towerX = (short)DAT_BuildingsState::instance.buildings[buildingID].x; + DAT_BuildingsState::instance.buildings[buildingID].noRubble = 0; + towerY = (short)DAT_BuildingsState::instance.buildings[buildingID].y; + MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::deleteBuilding, DAT_BuildingsState::ptr)( + buildingID); + towerSize = 6; + towerCommand = OpenSHC::Commands::M_MAPPER_TOWER4_DESTROYED; + replaced = 1; + break; + case OpenSHC::Map::Buildings::BT_TOWER5: + MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::processDamageToUnitsOnBuilding, + DAT_BuildingsState::ptr)(buildingID, 0x32); + towerOwner = DAT_BuildingsState::instance.buildings[buildingID].owner; + towerX = (short)DAT_BuildingsState::instance.buildings[buildingID].x; + DAT_BuildingsState::instance.buildings[buildingID].noRubble = 0; + towerY = (short)DAT_BuildingsState::instance.buildings[buildingID].y; + MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::deleteBuilding, DAT_BuildingsState::ptr)( + buildingID); + towerSize = 6; + towerCommand = OpenSHC::Commands::M_MAPPER_TOWER5_DESTROYED; + replaced = 1; + break; + } + + if (replaced != 0) { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::placeBuilding, this)( + towerOwner, towerX, towerY, towerCommand, towerSize, 0xf); + MACRO_CALL_MEMBER(OpenSHC::Audio::SFX::SFXState_Func::playSFXAtLocation, DAT_SFXState::ptr)( + towerX, towerY, OpenSHC::DE::SHCDE::FX_TOWER_SMASH); + destroyed = TRUE; + } else if (destroyNormally) { + short rubbleOwner = DAT_BuildingsState::instance.buildings[buildingID].owner; + this->showNoRubbleWhenDestroyingBuilding + = DAT_BuildingDefinedData::instance.BuildingShowRubbleWhenDestroyed[destroyedType] == 0; + MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::destroyBuilding, DAT_BuildingsState::ptr)( + buildingID); + MACRO_CALL_MEMBER(OpenSHC::Audio::SFX::SFXState_Func::playSFXAtLocation, DAT_SFXState::ptr)( + (short)DAT_BuildingsState::instance.buildings[buildingID].x, + (short)DAT_BuildingsState::instance.buildings[buildingID].y, OpenSHC::DE::SHCDE::FX_BUILDING_SMASH); + if (DAT_GameSynchronyState::instance.currentGameMode != OpenSHC::Game::GM_SOLITARY + && playerID == DAT_GameSynchronyState::instance.currentPlayerSlotID + && DAT_GameState::instance.mapAndTime.playerTeams[rubbleOwner] + != DAT_GameState::instance.mapAndTime + .playerTeams[DAT_GameSynchronyState::instance.currentPlayerSlotID] + && DAT_GameCore::instance.genieVoiceActive != FALSE) { + if (destroyedType == 0x13 || destroyedType == 0xb) { + /* "Excellent" */ + MACRO_CALL_MEMBER(OpenSHC::Audio::SFX::SFXState_Func::playWAVSFX, DAT_SFXState::ptr)( + "Genie_23.wav"); + } + if (destroyedType == 8 || destroyedType == 9) { + /* "Bravo" */ + MACRO_CALL_MEMBER(OpenSHC::Audio::SFX::SFXState_Func::playWAVSFX, DAT_SFXState::ptr)( + "Genie_24.wav"); + } + } + destroyed = TRUE; + } + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::updateWalkAndPathLayer, + DAT_PathFindingState::ptr)(7, xPosition, yPosition); + return ~-(uint)replaced & destroyed; + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/processEntityDamageToBuildingCollateral.cpp b/src/OpenSHC/Map/TileMapState/processEntityDamageToBuildingCollateral.cpp new file mode 100644 index 0000000000..ffb2215476 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/processEntityDamageToBuildingCollateral.cpp @@ -0,0 +1,406 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/AI/AICState.func.hpp" +#include "OpenSHC/Audio/SFX/SFXState.func.hpp" +#include "OpenSHC/Map/Buildings/BuildingsState.func.hpp" +#include "OpenSHC/Map/Entities.func.hpp" +#include "OpenSHC/Map/Entities/EntityState.func.hpp" +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" +#include "OpenSHC/Map/Units/UnitsState.func.hpp" +#include "OpenSHC/Commands/MappersEnum.hpp" +#include "OpenSHC/DE/SHCDE/eSFX.hpp" +#include "OpenSHC/Game/GameMode.hpp" +#include "OpenSHC/Map/Buildings/BuildingLogicalState.hpp" +#include "OpenSHC/Map/Buildings/BuildingType.hpp" +#include "OpenSHC/Map/Entities/EntityType.hpp" +#include "OpenSHC/Map/Units/States/UnitState.hpp" +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +#include "OpenSHC/Globals/DAT_AICState.hpp" +#include "OpenSHC/Globals/DAT_BuildingDefinedData.hpp" +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_EntityState.hpp" +#include "OpenSHC/Globals/DAT_GameCore.hpp" +#include "OpenSHC/Globals/DAT_GameState.hpp" +#include "OpenSHC/Globals/DAT_GameSynchronyState.hpp" +#include "OpenSHC/Globals/DAT_PathFindingState.hpp" +#include "OpenSHC/Globals/DAT_SFXState.hpp" +#include "OpenSHC/Globals/DAT_UnitsState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_BUILDING; + using OpenSHC::Map::LogicHelpers::L_CRENEL; + using OpenSHC::Map::LogicHelpers::L_CRENEL_VARIATIONUnk; + using OpenSHC::Map::LogicHelpers::L_KEEP_NON_MANOR_HOUSE; + using OpenSHC::Map::LogicHelpers::L_PLAIN2_AND_PITCH; + using OpenSHC::Map::LogicHelpers::L_STAIRS; + using OpenSHC::Map::LogicHelpers::L_STOCKPILEUnk; + using OpenSHC::Map::LogicHelpers::L_UNKNOWN_WALL_RELATED; + using OpenSHC::Map::LogicHelpers::L_WALL_OR_GATEHOUSE; + + using OpenSHC::Commands::MappersEnum; + using OpenSHC::DE::SHCDE::eSFX; + using OpenSHC::Game::GameMode; + using OpenSHC::Map::Buildings::BuildingLogicalState; + using OpenSHC::Map::Buildings::BuildingType; + using OpenSHC::Map::Entities::EntityType; + using OpenSHC::Map::Units::States::UnitState; + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x00517790 + void TileMapState::processEntityDamageToBuildingCollateral( + int tile, uint x, uint y, int damage, int playerID, undefined4 unused, int unitID) + { + uint baseY = y; + int baseTile = tile; + /* a negative player id is a request to spare that player's own team */ + bool spareOwnTeam = false; + if (playerID < 0) { + playerID = -playerID; + if (DAT_GameSynchronyState::instance.currentPlayerFullIDArray[playerID] == -1) { + spareOwnTeam = true; + } + } + + for (int index = 0; index < 9; index++) { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getTileForBrush, this)( + 0, index, &tile, (int*)&y, baseTile, baseY); + uint logic = this->LogicLayer[tile]; + if ((logic & (L_BUILDING | L_KEEP_NON_MANOR_HOUSE)) == 0 && this->BuildingLayer[tile] == 0) { + /* bare wall: grind its height down towards the ground it stands on */ + if ((logic & L_WALL_OR_GATEHOUSE) == 0 || (logic & L_STOCKPILEUnk) != 0) { + continue; + } + uint wallOwner = this->WallOwnerLayer[tile] & 7; + if (spareOwnTeam + && DAT_GameState::instance.mapAndTime.playerTeams[playerID] + == DAT_GameState::instance.mapAndTime.playerTeams[wallOwner + 1]) { + continue; + } + DAT_GameState::instance.playerDataArray[wallOwner + 1].defensesDamagedByPlayer = (short)playerID; + if (unitID != 0) { + if (DAT_GameState::instance.mapAndTime.playerTeams[wallOwner + 1] + == DAT_GameState::instance.mapAndTime.playerTeams[playerID]) { + DAT_UnitsState::instance.units[unitID].friendlyFireCounterUnk + = DAT_UnitsState::instance.units[unitID].friendlyFireCounterUnk + 1; + } else { + DAT_UnitsState::instance.units[unitID].friendlyFireCounterUnk = 0; + } + } + DAT_GameCore::instance.cowPoisonTrackerUnk = DAT_GameCore::instance.cowPoisonTrackerUnk + damage * 10; + for (int hit = 0; hit < damage; hit++) { + if (this->HeightLayer[tile] <= this->DefaultHeightLayer[tile]) { + MACRO_CALL_MEMBER(OpenSHC::Map::Entities::EntityState_Func::destroyEntitiesOnTile, + DAT_EntityState::ptr)(tile); + this->LogicLayer[tile] = this->LogicLayer[tile] + & ~(L_CRENEL_VARIATIONUnk | L_UNKNOWN_WALL_RELATED | L_STAIRS | L_CRENEL + | L_PLAIN2_AND_PITCH); + this->HeightLayer[tile] = this->DefaultHeightLayer[tile]; + this->DamageLayer[tile] = 0; + MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::PathFindingState_Func::updatePathLinkagesInAllEightDirections, + DAT_PathFindingState::ptr)(y, tile); + DAT_PathFindingState::instance.toggleUpdateSeparateAreaTileMap = 1; + this->field204_0x554a30 = 1; + break; + } + this->HeightLayer[tile] = this->HeightLayer[tile] - 1; + if ((char)this->DamageLayer[tile] < 200) { + this->DamageLayer[tile] = this->DamageLayer[tile] + 1; + } + } + continue; + } + + int buildingID = this->BuildingLayer[tile]; + if (DAT_BuildingsState::instance.buildings[buildingID].logicalState == (BuildingLogicalState)0 + || DAT_BuildingsState::instance.buildings[buildingID].logicalState + == OpenSHC::Map::Buildings::BLS_REMOVE) { + continue; + } + int health = DAT_BuildingsState::instance.buildings[buildingID].currentHealth; + if (health == 0) { + continue; + } + int buildingType = (short)DAT_BuildingsState::instance.buildings[buildingID].buildingType; + if (DAT_BuildingDefinedData::instance.BuildingTypeHasHealth[buildingType] == 0) { + continue; + } + if ((logic & 0xf000000) != 0 || (logic & L_STOCKPILEUnk) != 0) { + continue; + } + if (spareOwnTeam + && DAT_GameState::instance.mapAndTime.playerTeams[playerID] + == DAT_GameState::instance.mapAndTime + .playerTeams[DAT_BuildingsState::instance.buildings[buildingID].owner]) { + continue; + } + + short newHealth = health - (short)damage; + DAT_GameCore::instance.cowPoisonTrackerUnk = DAT_GameCore::instance.cowPoisonTrackerUnk + damage * 10; + DAT_BuildingsState::instance.buildings[buildingID].currentHealth = newHealth; + switch (buildingType) { + case 0x2d: + case 0x2e: + case 0x4a: + case 0x4b: + case 0x4c: + case 0x4d: + case 0x4e: + DAT_GameState::instance.playerDataArray[DAT_BuildingsState::instance.buildings[buildingID].owner] + .defensesDamagedByPlayer = (short)playerID; + } + if (unitID != 0) { + if (DAT_GameState::instance.mapAndTime + .playerTeams[DAT_BuildingsState::instance.buildings[buildingID].owner] + == DAT_GameState::instance.mapAndTime.playerTeams[playerID]) { + DAT_UnitsState::instance.units[unitID].friendlyFireCounterUnk + = DAT_UnitsState::instance.units[unitID].friendlyFireCounterUnk + 1; + } else { + DAT_UnitsState::instance.units[unitID].friendlyFireCounterUnk = 0; + } + } + if (newHealth > 0) { + continue; + } + + if (buildingType != 0x4f && (buildingType < 0x56 || buildingType > 0x59)) { + int owner = DAT_BuildingsState::instance.buildings[buildingID].owner; + DAT_GameSynchronyState::instance.finalResults.finalBuildingsBurned[playerID] + = DAT_GameSynchronyState::instance.finalResults.finalBuildingsBurned[playerID] + 1; + DAT_GameSynchronyState::instance.finalResults.finalBuidingsDestroyed[owner] + = DAT_GameSynchronyState::instance.finalResults.finalBuidingsDestroyed[owner] + 1; + /* a per-attacker tally inside the owner's player data, 0x20 apart */ + int* tally + = (int*)((char*)&DAT_GameState::instance.playerDataArray[owner].attackedByPlayerArrayUnk[0][1] + + playerID * 0x20); + *tally = *tally + 1; + } + switch (buildingType) { + case 0x1c: + case 0x2d: + case 0x2e: + case 0x4a: + case 0x4b: + case 0x4c: + case 0x4d: + case 0x4e: + MACRO_CALL_MEMBER(OpenSHC::AI::AICState_Func::playAnger2BikFromPlayerToPlayer, DAT_AICState::ptr)( + DAT_BuildingsState::instance.buildings[buildingID].owner, playerID); + break; + default: + MACRO_CALL_MEMBER(OpenSHC::AI::AICState_Func::playVictory2BikFromPlayerToPlayer, DAT_AICState::ptr)( + DAT_BuildingsState::instance.buildings[buildingID].owner, playerID); + } + + bool destroyNormally = false; + int towerX; + int towerY; + short towerOwner; + switch (DAT_BuildingsState::instance.buildings[buildingID].buildingType) { + case OpenSHC::Map::Buildings::BT_OILSMELTER: + if (DAT_BuildingsState::instance.buildings[buildingID].resources[7] == 0) { + destroyNormally = true; + break; + } + { + /* a smelter with oil in it goes up, and a full one throws burning oil about */ + int oilAmount = DAT_BuildingsState::instance.buildings[buildingID].resources[7]; + uint smelterTile = DAT_BuildingsState::instance.buildings[buildingID].currentTilePositionAdjusted; + int smelterX = (short)DAT_BuildingsState::instance.buildings[buildingID].x; + int smelterOwner = DAT_BuildingsState::instance.buildings[buildingID].owner; + DAT_BuildingsState::instance.buildings[buildingID].noRubble = 0; + int smelterY = (short)DAT_BuildingsState::instance.buildings[buildingID].y; + MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::deleteBuilding, + DAT_BuildingsState::ptr)(buildingID); + if (oilAmount < 5) { + MACRO_CALL(OpenSHC::Map::Entities_Func::SetPlaceOnFire)( + smelterOwner, smelterX * 8 + 0x10, smelterY * 8 + 0x10, this->HeightLayer[smelterTile], 3); + } else { + MACRO_CALL(OpenSHC::Map::Entities_Func::SetPlaceOnFire)( + smelterOwner, smelterX * 8 + 0x10, smelterY * 8 + 0x10, this->HeightLayer[smelterTile], 5); + MACRO_CALL_MEMBER( + OpenSHC::Map::Entities::EntityState_Func::spawnProjectileEntity, DAT_EntityState::ptr)(0, + smelterOwner, 0, smelterX * 8 + 0x10, smelterY * 8 + 0x10, this->HeightLayer[smelterTile], + 0, 0, 0, OpenSHC::Map::Entities::EntityTypeInt__ET_EXPLOSION, 0); + } + MACRO_CALL_MEMBER(OpenSHC::Audio::SFX::SFXState_Func::playSFXAtLocation, DAT_SFXState::ptr)( + smelterX, smelterY, OpenSHC::DE::SHCDE::FX_IGNITE_PITCH); + } + break; + case OpenSHC::Map::Buildings::BT_GATEHOUSELARGE: + case OpenSHC::Map::Buildings::BT_GATEHOUSESMALL: { + /* a gatehouse takes its drawbridges with it */ + int bridge = MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::findParticularBuilding, + DAT_BuildingsState::ptr)(DAT_BuildingsState::instance.buildings[buildingID].owner, + (short)DAT_BuildingsState::instance.buildings[buildingID].x, + (short)DAT_BuildingsState::instance.buildings[buildingID].y, + DAT_BuildingsState::instance.buildings[buildingID].widthOrHeight, + OpenSHC::Map::Buildings::BT_DRAWBRIDGE, 0); + if (bridge != 0) { + this->showNoRubbleWhenDestroyingBuilding + = DAT_BuildingDefinedData::instance.BuildingShowRubbleWhenDestroyed + [(short)DAT_BuildingsState::instance.buildings[bridge].buildingType] + == 0; + MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::destroyBuilding, DAT_BuildingsState::ptr)(bridge); + bridge = MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::findParticularBuilding, + DAT_BuildingsState::ptr)(DAT_BuildingsState::instance.buildings[buildingID].owner, + (short)DAT_BuildingsState::instance.buildings[buildingID].x, + (short)DAT_BuildingsState::instance.buildings[buildingID].y, + DAT_BuildingsState::instance.buildings[buildingID].widthOrHeight, + OpenSHC::Map::Buildings::BT_DRAWBRIDGE, bridge); + if (bridge != 0) { + this->showNoRubbleWhenDestroyingBuilding + = DAT_BuildingDefinedData::instance.BuildingShowRubbleWhenDestroyed + [(short)DAT_BuildingsState::instance.buildings[bridge].buildingType] + == 0; + MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::destroyBuilding, + DAT_BuildingsState::ptr)(bridge); + } + } + ushort gateY = DAT_BuildingsState::instance.buildings[buildingID].y; + ushort gateX = DAT_BuildingsState::instance.buildings[buildingID].x; + MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::processDamageToUnitsOnBuilding, + DAT_BuildingsState::ptr)(buildingID, 0x32); + this->showNoRubbleWhenDestroyingBuilding + = DAT_BuildingDefinedData::instance.BuildingShowRubbleWhenDestroyed + [(short)DAT_BuildingsState::instance.buildings[buildingID].buildingType] + == 0; + MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::destroyBuilding, DAT_BuildingsState::ptr)(buildingID); + MACRO_CALL_MEMBER(OpenSHC::Audio::SFX::SFXState_Func::playSFXAtLocation, DAT_SFXState::ptr)( + (short)gateX, (short)gateY, OpenSHC::DE::SHCDE::FX_TOWER_SMASH); + } break; + case OpenSHC::Map::Buildings::BT_TUNNEL: { + /* the tunneller inside is buried where he stands */ + uint tunneller = DAT_BuildingsState::instance.buildings[buildingID].unitRefID; + if (DAT_UnitsState::instance.units[tunneller].state.generic + != (OpenSHC::Map::Units::States::US_STAND_UPUnk | OpenSHC::Map::Units::States::US_IDLEUnk)) { + DAT_UnitsState::instance.units[tunneller].totalSizeOfPathPlan + = DAT_UnitsState::instance.units[tunneller].currentIndexInPathPlan; + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::applyTunnelDamageAlongPathPlan, + DAT_UnitsState::ptr)(tunneller); + } + DAT_UnitsState::instance.units[tunneller].state.generic = OpenSHC::Map::Units::States::US_DISAPPEAR; + DAT_UnitsState::instance.units[tunneller].disappearFadeAlphaCountdown = 0x20; + DAT_UnitsState::instance.units[tunneller].updateTickTracker = 0x20; + } + destroyNormally = true; + break; + default: + destroyNormally = true; + break; + case OpenSHC::Map::Buildings::BT_SIEGETOWER_PLACED: { + int rider = DAT_BuildingsState::instance.buildings[buildingID].unitRefID; + if (rider != 0 + && DAT_BuildingsState::instance.buildings[buildingID].unitRefUID + == DAT_UnitsState::instance.units[rider].uid) { + DAT_UnitsState::instance.units[rider].state.generic = OpenSHC::Map::Units::States::US_DISAPPEAR; + DAT_UnitsState::instance.units[rider].disappearFadeAlphaCountdown = 0; + DAT_UnitsState::instance.units[rider].updateTickTracker = 0; + DAT_UnitsState::instance.units[rider].workplaceBuildingID_1 = 0; + } + DAT_BuildingsState::instance.buildings[buildingID].noRubble = 0; + MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::deleteBuilding, DAT_BuildingsState::ptr)(buildingID); + } break; + case OpenSHC::Map::Buildings::BT_TOWER1: + MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::processDamageToUnitsOnBuilding, + DAT_BuildingsState::ptr)(buildingID, 0x19); + towerX = DAT_BuildingsState::instance.buildings[buildingID].x; + towerOwner = DAT_BuildingsState::instance.buildings[buildingID].owner; + DAT_BuildingsState::instance.buildings[buildingID].noRubble = 0; + towerY = DAT_BuildingsState::instance.buildings[buildingID].y; + MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::deleteBuilding, DAT_BuildingsState::ptr)(buildingID); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::placeBuilding, this)( + towerOwner, (short)towerX, (short)towerY, OpenSHC::Commands::M_MAPPER_TOWER1_DESTROYED, 3, 0xf); + break; + case OpenSHC::Map::Buildings::BT_TOWER2: + MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::processDamageToUnitsOnBuilding, + DAT_BuildingsState::ptr)(buildingID, 0x32); + towerX = DAT_BuildingsState::instance.buildings[buildingID].x; + towerOwner = DAT_BuildingsState::instance.buildings[buildingID].owner; + DAT_BuildingsState::instance.buildings[buildingID].noRubble = 0; + towerY = DAT_BuildingsState::instance.buildings[buildingID].y; + MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::deleteBuilding, DAT_BuildingsState::ptr)(buildingID); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::placeBuilding, this)( + towerOwner, (short)towerX, (short)towerY, OpenSHC::Commands::M_MAPPER_TOWER2_DESTROYED, 4, 0xf); + break; + case OpenSHC::Map::Buildings::BT_TOWER3: + MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::processDamageToUnitsOnBuilding, + DAT_BuildingsState::ptr)(buildingID, 0x32); + towerX = DAT_BuildingsState::instance.buildings[buildingID].x; + towerOwner = DAT_BuildingsState::instance.buildings[buildingID].owner; + DAT_BuildingsState::instance.buildings[buildingID].noRubble = 0; + towerY = DAT_BuildingsState::instance.buildings[buildingID].y; + MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::deleteBuilding, DAT_BuildingsState::ptr)(buildingID); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::placeBuilding, this)( + towerOwner, (short)towerX, (short)towerY, OpenSHC::Commands::M_MAPPER_TOWER3_DESTROYED, 5, 0xf); + break; + case OpenSHC::Map::Buildings::BT_TOWER4: + MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::processDamageToUnitsOnBuilding, + DAT_BuildingsState::ptr)(buildingID, 0x32); + towerX = DAT_BuildingsState::instance.buildings[buildingID].x; + towerOwner = DAT_BuildingsState::instance.buildings[buildingID].owner; + DAT_BuildingsState::instance.buildings[buildingID].noRubble = 0; + towerY = DAT_BuildingsState::instance.buildings[buildingID].y; + MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::deleteBuilding, DAT_BuildingsState::ptr)(buildingID); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::placeBuilding, this)( + towerOwner, (short)towerX, (short)towerY, OpenSHC::Commands::M_MAPPER_TOWER4_DESTROYED, 6, 0xf); + break; + case OpenSHC::Map::Buildings::BT_TOWER5: + MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::processDamageToUnitsOnBuilding, + DAT_BuildingsState::ptr)(buildingID, 0x32); + towerX = DAT_BuildingsState::instance.buildings[buildingID].x; + towerOwner = DAT_BuildingsState::instance.buildings[buildingID].owner; + DAT_BuildingsState::instance.buildings[buildingID].noRubble = 0; + towerY = DAT_BuildingsState::instance.buildings[buildingID].y; + MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::deleteBuilding, DAT_BuildingsState::ptr)(buildingID); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::placeBuilding, this)( + towerOwner, (short)towerX, (short)towerY, OpenSHC::Commands::M_MAPPER_TOWER5_DESTROYED, 6, 0xf); + break; + } + + if (destroyNormally) { + int destroyedType = (short)DAT_BuildingsState::instance.buildings[buildingID].buildingType; + int destroyedOwner = DAT_BuildingsState::instance.buildings[buildingID].owner; + this->showNoRubbleWhenDestroyingBuilding + = DAT_BuildingDefinedData::instance.BuildingShowRubbleWhenDestroyed[destroyedType] == 0; + MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::destroyBuilding, DAT_BuildingsState::ptr)(buildingID); + MACRO_CALL_MEMBER(OpenSHC::Audio::SFX::SFXState_Func::playSFXAtLocation, DAT_SFXState::ptr)( + (short)DAT_BuildingsState::instance.buildings[buildingID].x, + (short)DAT_BuildingsState::instance.buildings[buildingID].y, OpenSHC::DE::SHCDE::FX_BUILDING_SMASH); + if (DAT_GameSynchronyState::instance.currentGameMode != OpenSHC::Game::GM_SOLITARY + && playerID == DAT_GameSynchronyState::instance.currentPlayerSlotID + && DAT_GameState::instance.mapAndTime.playerTeams[destroyedOwner] + != DAT_GameState::instance.mapAndTime + .playerTeams[DAT_GameSynchronyState::instance.currentPlayerSlotID] + && DAT_GameCore::instance.genieVoiceActive != FALSE) { + if (destroyedType == 0x13 || destroyedType == 0xb) { + /* "Excellent" */ + MACRO_CALL_MEMBER(OpenSHC::Audio::SFX::SFXState_Func::playWAVSFX, DAT_SFXState::ptr)( + "Genie_23.wav"); + } + if (destroyedType == 8 || destroyedType == 9) { + /* "Bravo" */ + MACRO_CALL_MEMBER(OpenSHC::Audio::SFX::SFXState_Func::playWAVSFX, DAT_SFXState::ptr)( + "Genie_24.wav"); + } + } + } + } + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::updateWalkAndPathLayer, + DAT_PathFindingState::ptr)(9, x, baseY); + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/propagateCliffEdgeFlagFromNeighbor.cpp b/src/OpenSHC/Map/TileMapState/propagateCliffEdgeFlagFromNeighbor.cpp new file mode 100644 index 0000000000..b9788e0eb2 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/propagateCliffEdgeFlagFromNeighbor.cpp @@ -0,0 +1,48 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L2_OASIS_GRASS; + using OpenSHC::Map::LogicHelpers::L2_STONES_OR_DRIVEN_SANDUnk; + using OpenSHC::Map::LogicHelpers::L2_THICK_SCRUB; + using OpenSHC::Map::LogicHelpers::L_RIVER; + + // FUNCTION: STRONGHOLDCRUSADER 0x004FC280 + void TileMapState::propagateCliffEdgeFlagFromNeighbor(int tile, int x, int y) + { + int height = this->HeightLayer[tile]; + if (this->Logic2Layer[tile] != 0) { + return; + } + + for (int index = 0; index < 8; index++) { + uint neighbourY = DAT_TerrainDefinedData::instance.field2345_0x372c[index].y + y; + uint neighbourX = DAT_TerrainDefinedData::instance.field2345_0x372c[index].x + x; + if (neighbourX > 399 || neighbourY > 399) { + continue; + } + if (DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[neighbourY * 400 + neighbourX] == 0) { + continue; + } + int neighbour = DAT_ViewportRenderState::instance.translationMatrix[neighbourY].addXgetTile + + DAT_TerrainDefinedData::instance.field2345_0x372c[index].x + x; + if ((this->LogicLayer[neighbour] & L_RIVER) == 0) { + continue; + } + if ((this->Logic2Layer[neighbour] & (L2_OASIS_GRASS | L2_STONES_OR_DRIVEN_SANDUnk)) == 0) { + continue; + } + if (this->HeightLayer[neighbour] < height) { + continue; + } + this->Logic2Layer[tile] = L2_THICK_SCRUB; + return; + } + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/raiseLand.cpp b/src/OpenSHC/Map/TileMapState/raiseLand.cpp new file mode 100644 index 0000000000..8be94bb432 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/raiseLand.cpp @@ -0,0 +1,86 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" + +#include "OpenSHC/Globals/DAT_PathFindingState.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_BORDER; + using OpenSHC::Map::LogicHelpers::L_BORDER_EDGE; + using OpenSHC::Map::LogicHelpers::L_BUILDING; + using OpenSHC::Map::LogicHelpers::L_KEEP_NON_MANOR_HOUSE; + using OpenSHC::Map::LogicHelpers::L_MARSH; + using OpenSHC::Map::LogicHelpers::L_MOAT; + using OpenSHC::Map::LogicHelpers::L_MOAT_DUG_OR_PLANNED; + using OpenSHC::Map::LogicHelpers::L_RIVER; + using OpenSHC::Map::LogicHelpers::L_ROCKY; + using OpenSHC::Map::LogicHelpers::L_SEA; + using OpenSHC::Map::LogicHelpers::L_WALL_OR_GATEHOUSE; + + // FUNCTION: STRONGHOLDCRUSADER 0x00501D90 + void TileMapState::raiseLand(int tile, uint y, uint brush, int change) + { + int baseTile = tile; + int brushSize = DAT_TerrainDefinedData::instance.BrushSizeArray[brush]; + /* the original reuses the brush parameter to hold the base y */ + brush = y; + for (int index = 0; index < brushSize; index++) { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getTileForBrush, this)( + 1, index, &tile, (int*)&y, baseTile, brush); + int brushTile = tile; + uint logic = this->LogicLayer[brushTile]; + if ((logic & (L_BORDER | L_BORDER_EDGE)) == 0 + && ((logic & (L_SEA | L_MARSH)) == 0 || this->editorAffectType != 0) + && ((logic & (L_SEA | L_MARSH)) != 0 || this->editorAffectType != 1) + && (logic + & (L_WALL_OR_GATEHOUSE | L_BUILDING | L_MOAT_DUG_OR_PLANNED | L_KEEP_NON_MANOR_HOUSE | L_MOAT)) + == 0 + && this->BuildingLayer[brushTile] == 0) { + int minHeight; + int maxHeight; + if ((logic & L_SEA) != 0) { + minHeight = 0; + maxHeight = 0; + } else if ((logic & (L_SEA | L_MARSH | L_MOAT)) != 0) { + minHeight = 0; + maxHeight = 20; + } else { + minHeight = 8; + maxHeight = 128; + } + this->LogicLayer[brushTile] &= ~L_ROCKY; + if ((this->LogicLayer[brushTile] & L_RIVER) != 0) { + this->HeightLayer[brushTile] += 8; + } + this->ChangedLayer[brushTile] = 2; + if ((int)this->HeightLayer[brushTile] <= minHeight) { + this->HeightLayer[brushTile] = (byte)minHeight; + } + if (this->HeightLayer[brushTile] > 0 || change >= 0) { + this->HeightLayer[brushTile] += (char)change; + this->Logic2Layer[brushTile] = 0; + } + if ((int)this->HeightLayer[brushTile] < minHeight) { + this->HeightLayer[brushTile] = (byte)minHeight; + } + if ((int)this->HeightLayer[brushTile] > maxHeight) { + this->HeightLayer[brushTile] = (byte)maxHeight; + } + this->DefaultHeightLayer[brushTile] = this->HeightLayer[brushTile]; + if ((this->LogicLayer[brushTile] & L_RIVER) != 0) { + this->HeightLayer[brushTile] -= 8; + } + MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::PathFindingState_Func::updatePathLinkagesInAllEightDirections, + DAT_PathFindingState::ptr)(y, brushTile); + } + } + this->forceUpdateTextureTilemap = 1; + this->forceUpdateLogicalAndMiscDisplayLayers = 1; + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/reassignWallOwnershipForPlayer.cpp b/src/OpenSHC/Map/TileMapState/reassignWallOwnershipForPlayer.cpp new file mode 100644 index 0000000000..ab5bf1f40c --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/reassignWallOwnershipForPlayer.cpp @@ -0,0 +1,60 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_WALL_OR_GATEHOUSE; + + // FUNCTION: STRONGHOLDCRUSADER 0x004F9000 + void TileMapState::reassignWallOwnershipForPlayer(int playerID, int newOwner) + { + for (int tileUnk = 0; tileUnk < 80400; tileUnk += 6) { + if ((this->LogicLayer[tileUnk + 0] & L_WALL_OR_GATEHOUSE) != 0) { + int building = this->BuildingLayer[tileUnk + 0]; + if (building != 0 ? DAT_BuildingsState::instance.buildings[building].owner == newOwner + : (this->WallOwnerLayer[tileUnk + 0] & 7) + 1 == playerID) { + this->WallOwnerLayer[tileUnk + 0] = this->WallOwnerLayer[tileUnk + 0] & 0xf8 | (char)newOwner - 1U; + } + } + if ((this->LogicLayer[tileUnk + 1] & L_WALL_OR_GATEHOUSE) != 0) { + int building = this->BuildingLayer[tileUnk + 1]; + if (building != 0 ? DAT_BuildingsState::instance.buildings[building].owner == newOwner + : (this->WallOwnerLayer[tileUnk + 1] & 7) + 1 == playerID) { + this->WallOwnerLayer[tileUnk + 1] = this->WallOwnerLayer[tileUnk + 1] & 0xf8 | (char)newOwner - 1U; + } + } + if ((this->LogicLayer[tileUnk + 2] & L_WALL_OR_GATEHOUSE) != 0) { + int building = this->BuildingLayer[tileUnk + 2]; + if (building != 0 ? DAT_BuildingsState::instance.buildings[building].owner == newOwner + : (this->WallOwnerLayer[tileUnk + 2] & 7) + 1 == playerID) { + this->WallOwnerLayer[tileUnk + 2] = this->WallOwnerLayer[tileUnk + 2] & 0xf8 | (char)newOwner - 1U; + } + } + if ((this->LogicLayer[tileUnk + 3] & L_WALL_OR_GATEHOUSE) != 0) { + int building = this->BuildingLayer[tileUnk + 3]; + if (building != 0 ? DAT_BuildingsState::instance.buildings[building].owner == newOwner + : (this->WallOwnerLayer[tileUnk + 3] & 7) + 1 == playerID) { + this->WallOwnerLayer[tileUnk + 3] = this->WallOwnerLayer[tileUnk + 3] & 0xf8 | (char)newOwner - 1U; + } + } + if ((this->LogicLayer[tileUnk + 4] & L_WALL_OR_GATEHOUSE) != 0) { + int building = this->BuildingLayer[tileUnk + 4]; + if (building != 0 ? DAT_BuildingsState::instance.buildings[building].owner == newOwner + : (this->WallOwnerLayer[tileUnk + 4] & 7) + 1 == playerID) { + this->WallOwnerLayer[tileUnk + 4] = this->WallOwnerLayer[tileUnk + 4] & 0xf8 | (char)newOwner - 1U; + } + } + if ((this->LogicLayer[tileUnk + 5] & L_WALL_OR_GATEHOUSE) != 0) { + int building = this->BuildingLayer[tileUnk + 5]; + if (building != 0 ? DAT_BuildingsState::instance.buildings[building].owner == newOwner + : (this->WallOwnerLayer[tileUnk + 5] & 7) + 1 == playerID) { + this->WallOwnerLayer[tileUnk + 5] = this->WallOwnerLayer[tileUnk + 5] & 0xf8 | (char)newOwner - 1U; + } + } + } + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/rebuildShowHiLayerFromHeights.cpp b/src/OpenSHC/Map/TileMapState/rebuildShowHiLayerFromHeights.cpp new file mode 100644 index 0000000000..a6d670a1bf --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/rebuildShowHiLayerFromHeights.cpp @@ -0,0 +1,24 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Map/MapConstants.hpp" + +namespace OpenSHC { +namespace Map { + + // FUNCTION: STRONGHOLDCRUSADER 0x004F79D0 + void TileMapState::rebuildShowHiLayerFromHeights() + { + for (int tile = 0; tile < MC_MAP_TILES_COUNT; tile += 8) { + this->ShowHiLayer[tile] = (uchar)this->heightBasedScreenYOffset[this->HeightLayer[tile]]; + this->ShowHiLayer[tile + 1] = (uchar)this->heightBasedScreenYOffset[this->HeightLayer[tile + 1]]; + this->ShowHiLayer[tile + 2] = (uchar)this->heightBasedScreenYOffset[this->HeightLayer[tile + 2]]; + this->ShowHiLayer[tile + 3] = (uchar)this->heightBasedScreenYOffset[this->HeightLayer[tile + 3]]; + this->ShowHiLayer[tile + 4] = (uchar)this->heightBasedScreenYOffset[this->HeightLayer[tile + 4]]; + this->ShowHiLayer[tile + 5] = (uchar)this->heightBasedScreenYOffset[this->HeightLayer[tile + 5]]; + this->ShowHiLayer[tile + 6] = (uchar)this->heightBasedScreenYOffset[this->HeightLayer[tile + 6]]; + this->ShowHiLayer[tile + 7] = (uchar)this->heightBasedScreenYOffset[this->HeightLayer[tile + 7]]; + } + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/removeMoat.cpp b/src/OpenSHC/Map/TileMapState/removeMoat.cpp new file mode 100644 index 0000000000..a6fe6d9aaf --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/removeMoat.cpp @@ -0,0 +1,45 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" +#include "OpenSHC/UI/MinimapViewState.func.hpp" +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +#include "OpenSHC/Globals/DAT_MinimapViewState.hpp" +#include "OpenSHC/Globals/DAT_PathFindingState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_MOAT; + + using OpenSHC::Map::LogicHelpers::L_MOAT; + + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x005113F0 + BOOLEnum TileMapState::removeMoat(uint moatID, int param_2) + { + this->moats[moatID].fillProgress = this->moats[moatID].fillProgress - 1; + if ((char)this->moats[moatID].fillProgress >= 1) { + return FALSE; + } + + this->HeightLayer[this->moats[moatID].tile] = 8; + this->LogicLayer[this->moats[moatID].tile] = this->LogicLayer[this->moats[moatID].tile] & ~L_MOAT; + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::updateWalkAndPathLayer, + DAT_PathFindingState::ptr)(2, this->moats[moatID].x, this->moats[moatID].y); + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::updatePathLinkagesInAllEightDirections, + DAT_PathFindingState::ptr)(this->moats[moatID].y, this->moats[moatID].tile); + DAT_PathFindingState::instance.toggleUpdateSeparateAreaTileMap = 1; + int tile = this->moats[moatID].tile; + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::clearMoatData, this)(moatID); + if (this->BuildingLayer[tile] != 0) { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::updateBuildingGraphicsLayer, this)( + this->BuildingLayer[tile]); + } + MACRO_CALL_MEMBER(OpenSHC::UI::MinimapViewState_Func::triggerMinimapRedraw, DAT_MinimapViewState::ptr)(1); + return TRUE; + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/renderPreviewMapperWithBrush.cpp b/src/OpenSHC/Map/TileMapState/renderPreviewMapperWithBrush.cpp new file mode 100644 index 0000000000..1867cbdb21 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/renderPreviewMapperWithBrush.cpp @@ -0,0 +1,192 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" +#include "OpenSHC/Commands/MappersEnum.hpp" +#include "OpenSHC/Game/GameMode.hpp" +#include "OpenSHC/Game/GameMode2.hpp" +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +#include "OpenSHC/Globals/DAT_GameCore.hpp" +#include "OpenSHC/Globals/DAT_GameState.hpp" +#include "OpenSHC/Globals/DAT_GameSynchronyState.hpp" +#include "OpenSHC/Globals/DAT_PathFindingState.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Commands::MappersEnum; + using OpenSHC::Game::GameMode; + using OpenSHC::Game::GameMode2; + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x00508A00 + void TileMapState::renderPreviewMapperWithBrush(uint x, uint y, MappersEnum mapper) + { + if (x > 399) { + return; + } + if (y > 399) { + return; + } + if (DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[y * 400 + x] == 0) { + return; + } + + int brushSize = DAT_TerrainDefinedData::instance.BrushSizeArray[this->editorActiveBrush]; + int baseTile = DAT_ViewportRenderState::instance.translationMatrix[y].addXgetTile + x; + if (mapper == OpenSHC::Commands::M_MAPPER_POND1 || mapper == OpenSHC::Commands::M_MAPPER_POND2_SMALL + || mapper == OpenSHC::Commands::M_MAPPER_POND3_LARGE1 + || mapper == OpenSHC::Commands::M_MAPPER_POND4_LARGE2) { + this->buildingPlacementFail = FALSE; + return; + } + this->buildingPlacementFail = TRUE; + if (mapper == OpenSHC::Commands::M_MAPPER_SIGNPOST) { + return; + } + + /* every mapper draws its own preview colour */ + ushort gfx; + if ((int)mapper > OpenSHC::Commands::M_MAPPER_DUNES) { + gfx = 0x38; + } else if (mapper == OpenSHC::Commands::M_MAPPER_DUNES) { + gfx = 0x3c; + } else { + switch (mapper) { + case OpenSHC::Commands::M_MAPPER_SEA: + case OpenSHC::Commands::M_MAPPER_SHALLOWS: + case OpenSHC::Commands::M_MAPPER_RIVER: + case OpenSHC::Commands::M_MAPPER_MARSH: + case OpenSHC::Commands::M_MAPPER_DUGMOAT: + case OpenSHC::Commands::M_MAPPER_MOAT: + gfx = 0x39; + break; + case OpenSHC::Commands::M_MAPPER_SCRUB: + case OpenSHC::Commands::M_MAPPER_DIRT: + gfx = 0x3c; + break; + case OpenSHC::Commands::M_MAPPER_BEACH: + case OpenSHC::Commands::M_MAPPER_FORD: + gfx = 0x3a; + break; + case OpenSHC::Commands::M_MAPPER_ROCKY: + case OpenSHC::Commands::M_MAPPER_STONES: + case OpenSHC::Commands::M_MAPPER_BOULDERS: + case OpenSHC::Commands::M_MAPPER_PEBBLES: + case OpenSHC::Commands::M_MAPPER_IRON: + gfx = 0x3b; + break; + case OpenSHC::Commands::M_MAPPER_CHESTNUT: + case OpenSHC::Commands::M_MAPPER_OAK: + case OpenSHC::Commands::M_MAPPER_PINE: + case OpenSHC::Commands::M_MAPPER_BIRCH: + case OpenSHC::Commands::M_MAPPER_SHRUB1A: + case OpenSHC::Commands::M_MAPPER_SHRUB1B: + case OpenSHC::Commands::M_MAPPER_SHRUB1C: + case OpenSHC::Commands::M_MAPPER_SHRUB1D: + case OpenSHC::Commands::M_MAPPER_SHRUB1E: + case OpenSHC::Commands::M_MAPPER_SHRUB2A: + case OpenSHC::Commands::M_MAPPER_SHRUB2B: + case OpenSHC::Commands::M_MAPPER_SHRUB2C: + case OpenSHC::Commands::M_MAPPER_SHRUB2D: + case OpenSHC::Commands::M_MAPPER_SHRUB2E: + case OpenSHC::Commands::M_MAPPER_SHRUB3A: + case OpenSHC::Commands::M_MAPPER_SHRUB3B: + case OpenSHC::Commands::M_MAPPER_SHRUB3C: + case OpenSHC::Commands::M_MAPPER_SHRUB3D: + case OpenSHC::Commands::M_MAPPER_DEER: + case OpenSHC::Commands::M_MAPPER_LION: + case OpenSHC::Commands::M_MAPPER_RABBIT: + case OpenSHC::Commands::M_MAPPER_CAMEL: + case OpenSHC::Commands::M_MAPPER_CROW_SEAGULL: + case OpenSHC::Commands::M_MAPPER_SEAGULL: + /* a single organism is placed on one tile, whatever the brush size */ + brushSize = 1; + case OpenSHC::Commands::M_MAPPER_RAISE: + case OpenSHC::Commands::M_MAPPER_LOWER: + case OpenSHC::Commands::M_MAPPER_EQUALISE: + case OpenSHC::Commands::M_MAPPER_MOUNTAIN: + case OpenSHC::Commands::M_MAPPER_HILL: + case OpenSHC::Commands::M_MAPPER_DELETE: + gfx = 0x3e; + break; + case OpenSHC::Commands::M_MAPPER_UNDUGMOAT: + case OpenSHC::Commands::M_MAPPER_OIL: + gfx = 0x3d; + break; + default: + gfx = 0x38; + } + } + + switch (mapper) { + case OpenSHC::Commands::M_MAPPER_UNDUGMOAT: + case OpenSHC::Commands::M_MAPPER_DUGMOAT: + case OpenSHC::Commands::M_MAPPER_MOAT: + case OpenSHC::Commands::M_MAPPER_ANTIMOAT: + /* a moat may not be dug too near an enemy, a signpost, or an opponent's buildings */ + if (DAT_GameCore::instance.gameMode_2 != OpenSHC::Game::GM_EDITOR + && DAT_GameCore::instance.gameMode_2 != OpenSHC::Game::GM_SIEGE_THAT) { + int enemyRange; + int searchRange; + if (DAT_GameSynchronyState::instance.currentGameMode == OpenSHC::Game::GM_SOLITARY) { + enemyRange = 0x1e; + searchRange = 30; + } else { + enemyRange = 0xf; + searchRange = 7; + } + if (MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::PathFindingState_Func::isEnemyTooCloseUnk, DAT_PathFindingState::ptr)( + DAT_GameSynchronyState::instance.currentPlayerSlotID, x, y, enemyRange) + != FALSE) { + gfx = 0x3e; + } + if (MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::isSignPostWithinDistance, + DAT_PathFindingState::ptr)(x, y, DAT_GameState::instance.mapAndTime.unk_signpostDistance + 5) + != FALSE) { + gfx = 0x3e; + } + if (DAT_GameSynchronyState::instance.currentGameMode != OpenSHC::Game::GM_SOLITARY) { + int buildRange + = MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getCastleBuildRangeForMapSize, this)(); + if (MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::isOpponentBuildingInRange, + DAT_PathFindingState::ptr)(DAT_GameSynchronyState::instance.currentPlayerSlotID, x, y, + searchRange, -1, -1, buildRange + 5) + != 0) { + gfx = 0x3e; + } + } + } + } + + int tile = DAT_ViewportRenderState::instance.translationMatrix[y].addXgetTile + x; + uint brushY = y; + if (mapper == OpenSHC::Commands::M_MAPPER_DUGMOAT || mapper == OpenSHC::Commands::M_MAPPER_UNDUGMOAT + || mapper == OpenSHC::Commands::M_MAPPER_MOAT || mapper == OpenSHC::Commands::M_MAPPER_ANTIMOAT) { + /* a moat preview always covers the nine tiles around the cursor */ + int index = 0; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getTileForBrush, this)( + 0, index, &tile, (int*)&brushY, baseTile, y); + index++; + this->ConstructionGFXLayer[tile] = gfx; + } while (index < 9); + return; + } + if (brushSize < 1) { + return; + } + int index = 0; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getTileForBrush, this)( + 1, index, &tile, (int*)&brushY, baseTile, y); + index++; + this->ConstructionGFXLayer[tile] = gfx; + } while (index < brushSize); + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/renderWallDragPreview.cpp b/src/OpenSHC/Map/TileMapState/renderWallDragPreview.cpp new file mode 100644 index 0000000000..b9e9f92d30 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/renderWallDragPreview.cpp @@ -0,0 +1,185 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Map/Buildings/BuildingsState.func.hpp" +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" +#include "OpenSHC/Globals/GMTotalPicturesProcessed.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_CRENEL; + using OpenSHC::Map::LogicHelpers::L_WALL_OR_GATEHOUSE; + + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x004F8BD0 + void TileMapState::renderWallDragPreview(int playerID, uint x1, uint y1, uint x2, uint y2, undefined4 command) + { + int budget = 0; + if (x1 > 399 || y1 > 399 || DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[y1 * 400 + x1] == 0) { + return; + } + if (x2 > 399 || y2 > 399 || DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[y2 * 400 + x2] == 0) { + return; + } + + this->DAT_WallTileCountCurrentDrag = 0; + int overshoot = 2; + if ((short)command == 0x1b) { + budget = this->maxWallHeightInPath; + if (this->field118_0x554920 == 0) { + this->ConstructionGFXLayer[DAT_ViewportRenderState::instance.translationMatrix[y1].addXgetTile + x1] + = (short)GMTotalPicturesProcessed::instance[6] + 0x13; + return; + } + } + + /* the drag walks one tile at a time towards (x2, y2), on whichever axis is further away */ + int upY = y1 - y2; + int downY = y2 - y1; + uint x = x1; + uint y = y1; + int leftX = x1 - x2; + int rightX = x2 - x1; + int* translation = &DAT_ViewportRenderState::instance.translationMatrix[y1].addXgetTile; + int tile; + do { + if ((short)command == 0x1b && budget < 0x18) { + break; + } + tile = *translation + x; + if ((short)command == 0x1b && (this->LogicLayer[tile] & L_WALL_OR_GATEHOUSE) != 0) { + break; + } + if (this->constructionTileCount <= this->DAT_WallTileCountCurrentDrag) { + break; + } + + /* a crenel dragged over an existing one does not count against the tile budget */ + bool onCrenel = false; + if ((short)command == 0x19 && (this->LogicLayer[tile] & L_CRENEL) != 0) { + onCrenel = true; + } + if ((this->LogicLayer[tile] & L_WALL_OR_GATEHOUSE) == 0 || this->DamageLayer[tile] != 0 || onCrenel) { + if (!onCrenel) { + this->DAT_WallTileCountCurrentDrag = this->DAT_WallTileCountCurrentDrag + 1; + } + if (this->illegalBuild == FALSE) { + if ((short)command == 0x19) { + this->ConstructionGFXLayer[tile] = (ushort)GMTotalPicturesProcessed::instance[6]; + } else if ((short)command == 0x2e) { + this->ConstructionGFXLayer[tile] = (ushort)GMTotalPicturesProcessed::instance[6] + 1; + } else if ((short)command == 0x1a) { + this->ConstructionGFXLayer[tile] = (ushort)GMTotalPicturesProcessed::instance[6] + 4; + } else if ((short)command == 0x1b) { + /* a stair climbs one graphic per eight units of height below the wall top */ + int steps = (budget - (int)(uint)this->HeightLayer[tile]) / 8 - 1; + if (steps > 0) { + if (steps > 10) { + steps = 10; + } + this->ConstructionGFXLayer[tile] + = (short)steps + 8 + (ushort)GMTotalPicturesProcessed::instance[6]; + } else { + this->DAT_WallTileCountCurrentDrag = this->DAT_WallTileCountCurrentDrag - 1; + } + } + } else if ((short)command == 0x19) { + this->ConstructionGFXLayer[tile] = (ushort)GMTotalPicturesProcessed::instance[6] + 0x13; + } else if ((short)command == 0x2e) { + this->ConstructionGFXLayer[tile] = (ushort)GMTotalPicturesProcessed::instance[6] + 0x13; + } else if ((short)command == 0x1a) { + this->ConstructionGFXLayer[tile] = (ushort)GMTotalPicturesProcessed::instance[6] + 0x14; + } else if ((short)command == 0x1b) { + this->ConstructionGFXLayer[tile] = (ushort)GMTotalPicturesProcessed::instance[6] + 0x13; + } + } + + int stepX = leftX; + if ((int)x < (int)x2) { + stepX = rightX; + } + int stepY = upY; + if ((int)y < (int)y2) { + stepY = downY; + } + if ((short)command == 0x1b) { + if (stepY < stepX) { + if ((int)x < (int)x2) { + leftX = leftX + 1; + x = x + 1; + rightX = rightX - 1; + } else { + leftX = leftX - 1; + x = x - 1; + rightX = rightX + 1; + } + } else if (stepY > 0) { + if ((int)y < (int)y2) { + translation = translation + 3; + y = y + 1; + upY = upY + 1; + downY = downY - 1; + } else { + translation = translation - 3; + y = y - 1; + upY = upY - 1; + downY = downY + 1; + } + } else { + overshoot = overshoot - 1; + } + } else { + if (stepX != 0) { + if ((int)x < (int)x2) { + leftX = leftX + 1; + x = x + 1; + rightX = rightX - 1; + } else { + leftX = leftX - 1; + x = x - 1; + rightX = rightX + 1; + } + } + if (stepY != 0) { + if ((int)y < (int)y2) { + translation = translation + 3; + y = y + 1; + upY = upY + 1; + downY = downY - 1; + } else { + translation = translation - 3; + y = y - 1; + upY = upY - 1; + downY = downY + 1; + } + } + if (x == x2 && y == y2) { + overshoot = overshoot - 1; + } + } + if (budget > 0x10 && overshoot == 2) { + budget = budget - 0x10; + } + } while (x != x2 || y != y2 || overshoot != 0); + + if (this->illegalBuild != FALSE) { + this->DAT_WallTileCountCurrentDrag = 0; + } + if (this->wallDragButtonUp != 0) { + return; + } + if ((short)command == 0x2e) { + MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::processWallBuildingLoss, + DAT_BuildingsState::ptr)(playerID, 0, this->DAT_WallTileCountCurrentDrag, 1); + return; + } + MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::processWallBuildingLoss, + DAT_BuildingsState::ptr)(playerID, this->DAT_WallTileCountCurrentDrag, 0, 1); + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/renderWallPlacementPreview.cpp b/src/OpenSHC/Map/TileMapState/renderWallPlacementPreview.cpp new file mode 100644 index 0000000000..77d94c1206 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/renderWallPlacementPreview.cpp @@ -0,0 +1,124 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" +#include "OpenSHC/Globals/GMTotalPicturesProcessed.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_BORDER; + using OpenSHC::Map::LogicHelpers::L_BORDER_EDGE; + using OpenSHC::Map::LogicHelpers::L_BUILDING; + + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x004FB9E0 + void TileMapState::renderWallPlacementPreview(uint x, uint y, short kind) + { + int index = 0; + int base = 0; + int size = 0; + if (x > 399) { + return; + } + if (y > 399) { + return; + } + if (DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[y * 400 + x] == 0) { + return; + } + this->buildingPlacementFail = FALSE; + /* every wall kind has its own footprint size and first graphic */ + if (kind == 0) { + size = 1; + base = 0x211; + } else if (kind == 1) { + size = 1; + base = 0x215; + } else if (kind == 2) { + size = 1; + base = 0x219; + } else if (kind == 3) { + size = 1; + base = 0x21d; + } else if (kind == 4) { + size = 2; + base = 0x1d1; + } else if (kind == 5) { + size = 2; + base = 0x1e1; + } else if (kind == 6) { + size = 2; + base = 0x1f1; + } else if (kind == 7) { + size = 2; + base = 0x201; + } else if (kind == 8) { + size = 3; + base = 0x141; + } else if (kind == 9) { + size = 3; + base = 0x165; + } else if (kind == 0xa) { + size = 3; + base = 0x189; + } else if (kind == 0xb) { + size = 3; + base = 0x1ad; + } else { + if (kind == 0xc) { + base = 0x41; + } else if (kind == 0xd) { + base = 0x81; + } else if (kind == 0xe) { + base = 0xc1; + } else if (kind == 0xf) { + base = 0x101; + } + if (base != 0) { + size = 4; + } + } + + int rotation = this->rockOrientation + this->mapOrientation; + if (this->editorRockType == 5) { + rotation = this->mapOrientation; + } + if (rotation >= 8) { + rotation = rotation - 8; + } + /* the rotation part of the graphic index does not change over the footprint */ + int variationStep = rotation / 2 * size * size; + + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)(index, size); + int tile = DAT_ViewportRenderState::instance.translationMatrix[this->buildingY + y].addXgetTile + + this->buildingX + x; + uint logic = this->LogicLayer[tile]; + if ((logic & (L_BORDER | L_BORDER_EDGE)) != 0) { + return; + } + if ((logic & L_BUILDING) != 0) { + return; + } + if (this->OrganismLayer[tile] != 0) { + return; + } + index++; + } while (index < this->constructionTileCount); + + index = 0; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)(index, size); + this->ConstructionGFXLayer[DAT_ViewportRenderState::instance.translationMatrix[this->buildingY + y] + .addXgetTile + + this->buildingX + x] = (short)this->buildingRotationRelatedValue + + (short)GMTotalPicturesProcessed::instance[0x38] + (short)variationStep + (short)base - 1; + index++; + } while (index < this->constructionTileCount); + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/resetAreaBasedOnLogicalLayer.cpp b/src/OpenSHC/Map/TileMapState/resetAreaBasedOnLogicalLayer.cpp new file mode 100644 index 0000000000..85a489bded --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/resetAreaBasedOnLogicalLayer.cpp @@ -0,0 +1,67 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Map/MapConstants.hpp" + +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_BORDER; + using OpenSHC::Map::LogicHelpers::L_BORDER_EDGE; + + // FUNCTION: STRONGHOLDCRUSADER 0x005127B0 + void TileMapState::resetAreaBasedOnLogicalLayer() + { + for (int tile = 0; tile < MC_MAP_TILES_COUNT; tile++) { + if ((this->LogicLayer[tile] & (L_BORDER | L_BORDER_EDGE)) == 0) { + continue; + } + + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::useEraserBrush, this)(tile + - DAT_ViewportRenderState::instance + .translationMatrix[DAT_ViewportRenderState::instance.tileTranslationMatrix_YComponent[tile]] + .addXgetTile, + DAT_ViewportRenderState::instance.tileTranslationMatrix_YComponent[tile], 1); + this->GfxLayer[tile] = 0; + this->AlphaGFXLayer[tile] = 0; + this->ConstructionGFXLayer[tile] = 0; + this->PillarGFXLayer[tile] = 1; + this->WallGFXLayer[tile] = 0; + this->FloatingLayer[tile] = 0; + this->UnitLayer[tile] = 0; + this->EntityLayer[tile] = 0; + this->EntityLayerLT25[tile] = 0; + this->BuildingLayer[tile] = 0; + this->LogicLayer[tile] = 0; + this->Logic2Layer[tile] = 0; + this->ChangedLayer[tile] = 0; + this->OrganismLayer[tile] = 0; + this->DamageLayer[tile] = 0; + this->MacroLayer[tile] = 0; + this->HeightLayer[tile] = 8; + this->DefaultHeightLayer[tile] = 8; + this->ShowHiLayer[tile] = 0; + this->MiscDisplayLayer[tile] = 0; + this->LuminesenceLayer[tile] = 0; + this->WallOwnerLayer[tile] = 0; + this->BuildingWasLayer[tile] = 0; + this->OccupancyLayer[tile] = 0; + this->AIZoneLayer[tile] = 0; + this->AIInfoLayer[tile] = 0; + this->unitDeathHeatMap[tile] = 0; + this->SEC_TileMap1104[tile] = 0; + this->SEC_PathfindingCostTileMap1105[0][tile] = 0; + this->SEC_PathfindingCostTileMap1105[1][tile] = 0; + this->SEC_PathfindingCostTileMap1105[2][tile] = 0; + this->SEC_PathfindingCostTileMap1105[3][tile] = 0; + this->SEC_PathfindingCostTileMap1105[4][tile] = 0; + this->SEC_PathfindingCostTileMap1105[5][tile] = 0; + this->SEC_PathfindingCostTileMap1105[6][tile] = 0; + this->SEC_PathfindingCostTileMap1105[7][tile] = 0; + this->SEC_PathfindingCostTileMap1105[8][tile] = 0; + } + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/resetHeightAndMapBorders.cpp b/src/OpenSHC/Map/TileMapState/resetHeightAndMapBorders.cpp new file mode 100644 index 0000000000..b0bc40a819 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/resetHeightAndMapBorders.cpp @@ -0,0 +1,107 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Map/MapConstants.hpp" +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" + +#include "OpenSHC/Globals/DAT_PathFindingState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_BORDER; + using OpenSHC::Map::LogicHelpers::L_BORDER_EDGE; + + // FUNCTION: STRONGHOLDCRUSADER 0x004F6CF0 + void TileMapState::resetHeightAndMapBorders(int mapSize) + { + int inset = (MC_MAP_XY_LIMIT - mapSize) / 2; + this->mapSize = mapSize; + for (int tile = 0; tile < MC_MAP_TILES_COUNT; tile++) { + if ((this->LogicLayer[tile] & (L_BORDER | L_BORDER_EDGE)) != 0) { + this->HeightLayer[tile] = this->DefaultHeightLayer[tile]; + } + this->LogicLayer[tile] = this->LogicLayer[tile] & ~(L_BORDER | L_BORDER_EDGE); + } + + /* the two outer diagonals of the diamond carry the border flags */ + int rowLength = 0; + int tile = 0; + do { + this->LogicLayer[tile] = this->LogicLayer[tile] | L_BORDER; + tile++; + if (rowLength > 0) { + this->LogicLayer[tile] = this->LogicLayer[tile] | L_BORDER_EDGE; + } + tile = tile + rowLength; + if (rowLength > 0 && (this->LogicLayer[tile - 1] & L_BORDER) == 0) { + this->LogicLayer[tile - 1] = L_BORDER_EDGE; + } + this->LogicLayer[tile] = L_BORDER; + rowLength = rowLength + 2; + tile++; + } while (rowLength < MC_MAP_XY_LIMIT); + + for (rowLength = 398; rowLength >= 0; rowLength = rowLength - 2) { + this->LogicLayer[tile] = L_BORDER; + tile++; + if (rowLength > 0) { + this->LogicLayer[tile] = L_BORDER_EDGE; + } + tile = tile + rowLength; + if (rowLength > 0 && (this->LogicLayer[tile - 1] & L_BORDER) == 0) { + this->LogicLayer[tile - 1] = L_BORDER_EDGE; + } + this->LogicLayer[tile] = L_BORDER; + tile++; + } + + /* and again inset by (400 - mapSize) / 2 for a map smaller than the full diamond */ + int row = 0; + tile = 0; + for (int skipped = 0; skipped < inset; skipped++) { + tile = tile + 2 + row; + row = row + 2; + } + int firstRow = row; + for (; row < MC_MAP_XY_LIMIT; row = row + 2) { + this->LogicLayer[tile + inset] = this->LogicLayer[tile + inset] | L_BORDER; + tile++; + if (row - inset > 0) { + this->LogicLayer[tile + inset] = this->LogicLayer[tile + inset] | L_BORDER_EDGE; + } + tile = tile + row; + if (row - inset > 0 && (this->LogicLayer[tile - inset] & L_BORDER) == 0) { + this->LogicLayer[tile - inset - 1] = this->LogicLayer[tile - inset - 1] | L_BORDER_EDGE; + } + this->LogicLayer[tile - inset] = this->LogicLayer[tile - inset] | L_BORDER; + tile++; + } + for (row = 398; row >= firstRow; row = row - 2) { + this->LogicLayer[tile + inset] = this->LogicLayer[tile + inset] | L_BORDER; + tile++; + if (row - inset > 0) { + this->LogicLayer[tile + inset] = this->LogicLayer[tile + inset] | L_BORDER_EDGE; + } + tile = tile + row; + if (row - inset > 0 && (this->LogicLayer[tile - inset] & L_BORDER) == 0) { + this->LogicLayer[tile - inset - 1] = this->LogicLayer[tile - inset - 1] | L_BORDER_EDGE; + } + this->LogicLayer[tile - inset] = this->LogicLayer[tile - inset] | L_BORDER; + tile++; + } + if (mapSize != MC_MAP_XY_LIMIT) { + MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::PathFindingState_Func::setWalkabilityBorderLogicLayerForSmallerMapSizes, + DAT_PathFindingState::ptr)(); + } + + /* every border tile ends up at the minimum height */ + for (int borderTile = 0; borderTile < MC_MAP_TILES_COUNT; borderTile++) { + if ((this->LogicLayer[borderTile] & (L_BORDER | L_BORDER_EDGE)) != 0) { + this->HeightLayer[borderTile] = 8; + } + } + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/resetTileAndClearMoat.cpp b/src/OpenSHC/Map/TileMapState/resetTileAndClearMoat.cpp new file mode 100644 index 0000000000..c461bd2adb --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/resetTileAndClearMoat.cpp @@ -0,0 +1,70 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Globals/DAT_LandscapeState.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_CRENEL; + using OpenSHC::Map::LogicHelpers::L_CRENEL_VARIATIONUnk; + using OpenSHC::Map::LogicHelpers::L_MOAT; + using OpenSHC::Map::LogicHelpers::L_MOAT_DUG_OR_PLANNED; + using OpenSHC::Map::LogicHelpers::L_PLAIN2_AND_PITCH; + using OpenSHC::Map::LogicHelpers::L_STAIRS; + using OpenSHC::Map::LogicHelpers::L_TREE; + using OpenSHC::Map::LogicHelpers::L_UNKNOWN_WALL_RELATED; + using OpenSHC::Map::LogicHelpers::L_WALL_OR_GATEHOUSE; + + using OpenSHC::Map::LogicHelpers::L_CRENEL; + using OpenSHC::Map::LogicHelpers::L_CRENEL_VARIATIONUnk; + using OpenSHC::Map::LogicHelpers::L_MOAT; + using OpenSHC::Map::LogicHelpers::L_MOAT_DUG_OR_PLANNED; + using OpenSHC::Map::LogicHelpers::L_PLAIN2_AND_PITCH; + using OpenSHC::Map::LogicHelpers::L_STAIRS; + using OpenSHC::Map::LogicHelpers::L_TREE; + using OpenSHC::Map::LogicHelpers::L_UNKNOWN_WALL_RELATED; + using OpenSHC::Map::LogicHelpers::L_WALL_OR_GATEHOUSE; + + // FUNCTION: STRONGHOLDCRUSADER 0x00507350 + void TileMapState::resetTileAndClearMoat(int tile) + { + int y = DAT_ViewportRenderState::instance.tileTranslationMatrix_YComponent[tile]; + int rowTile = DAT_ViewportRenderState::instance.translationMatrix[y].addXgetTile; + this->LogicLayer[tile] = this->LogicLayer[tile] + & ~(L_PLAIN2_AND_PITCH | L_WALL_OR_GATEHOUSE | L_CRENEL | L_STAIRS | L_UNKNOWN_WALL_RELATED + | L_CRENEL_VARIATIONUnk); + this->HeightLayer[tile] = DAT_TileMapState::instance.DefaultHeightLayer[tile]; + this->DamageLayer[tile] = 0; + if ((this->LogicLayer[tile] & L_TREE) != 0) { + int treeID = this->OrganismLayer[tile]; + if (treeID < 2000) { + switch (DAT_LandscapeState::instance.trees[treeID].treeType) { + case (TreeType)5: + case (TreeType)6: + case (TreeType)7: + case (TreeType)8: + case (TreeType)9: + case (TreeType)10: + case (TreeType)11: + case (TreeType)12: + case (TreeType)13: + case (TreeType)14: + case (TreeType)16: + case (TreeType)17: + case (TreeType)18: + case (TreeType)19: + DAT_LandscapeState::instance.trees[treeID].state = 3; + } + } + } + if ((this->LogicLayer[tile] & (L_MOAT | L_MOAT_DUG_OR_PLANNED)) != 0) { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::clearMoatDataAtTile, this)(tile - rowTile, y); + this->LogicLayer[tile] = this->LogicLayer[tile] & ~(L_MOAT | L_MOAT_DUG_OR_PLANNED); + } + this->MiscDisplayLayer[tile] = this->MiscDisplayLayer[tile] & 0xfc3f; + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/resetTileToDefaultState.cpp b/src/OpenSHC/Map/TileMapState/resetTileToDefaultState.cpp new file mode 100644 index 0000000000..4d7aa9e32c --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/resetTileToDefaultState.cpp @@ -0,0 +1,31 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Map/Entities/EntityState.func.hpp" +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" + +#include "OpenSHC/Globals/DAT_EntityState.hpp" +#include "OpenSHC/Globals/DAT_PathFindingState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_CRENEL; + using OpenSHC::Map::LogicHelpers::L_CRENEL_VARIATIONUnk; + using OpenSHC::Map::LogicHelpers::L_STAIRS; + using OpenSHC::Map::LogicHelpers::L_UNKNOWN_WALL_RELATED; + using OpenSHC::Map::LogicHelpers::L_WALL_OR_GATEHOUSE; + + // FUNCTION: STRONGHOLDCRUSADER 0x004F81D0 + void TileMapState::resetTileToDefaultState(int param_1, uint param_2, uint param_3) + { + this->LogicLayer[param_1] = this->LogicLayer[param_1] + & ~(L_WALL_OR_GATEHOUSE | L_CRENEL | L_STAIRS | L_UNKNOWN_WALL_RELATED | L_CRENEL_VARIATIONUnk); + this->HeightLayer[param_1] = this->DefaultHeightLayer[param_1]; + MACRO_CALL_MEMBER(OpenSHC::Map::Entities::EntityState_Func::destroyEntitiesOnTile, DAT_EntityState::ptr)( + param_1); + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::updateWalkAndPathLayer, + DAT_PathFindingState::ptr)(5, param_2, param_3); + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/returnMoatIDForPlayerIDs.cpp b/src/OpenSHC/Map/TileMapState/returnMoatIDForPlayerIDs.cpp new file mode 100644 index 0000000000..71e68644fa --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/returnMoatIDForPlayerIDs.cpp @@ -0,0 +1,18 @@ +#include "../TileMapState.func.hpp" + +namespace OpenSHC { +namespace Map { + + // FUNCTION: STRONGHOLDCRUSADER 0x00500290 + int TileMapState::returnMoatIDForPlayerIDs(int playerID, int playerID2) + { + for (int moatID = 1; moatID < this->currentMoatCount; moatID++) { + if (this->moats[moatID].tile == playerID && this->moats[moatID].owner == playerID2) { + return moatID; + } + } + return 0; + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/returnOwnedMoatAtTile.cpp b/src/OpenSHC/Map/TileMapState/returnOwnedMoatAtTile.cpp new file mode 100644 index 0000000000..e31e800025 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/returnOwnedMoatAtTile.cpp @@ -0,0 +1,18 @@ +#include "../TileMapState.func.hpp" + +namespace OpenSHC { +namespace Map { + + // FUNCTION: STRONGHOLDCRUSADER 0x00500250 + int TileMapState::returnOwnedMoatAtTile(int targetedTile) + { + for (int moatID = 1; moatID < this->currentMoatCount; moatID++) { + if (this->moats[moatID].owner != 0 && this->moats[moatID].tile == targetedTile) { + return moatID; + } + } + return 0; + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/returnSomeHeight.cpp b/src/OpenSHC/Map/TileMapState/returnSomeHeight.cpp new file mode 100644 index 0000000000..77f066e3d7 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/returnSomeHeight.cpp @@ -0,0 +1,79 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Map/Buildings/BuildingsState.func.hpp" + +#include "OpenSHC/Globals/DAT_BuildingDefinedData.hpp" +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_LandscapeState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_BUILDING; + using OpenSHC::Map::LogicHelpers::L_KEEP_NON_MANOR_HOUSE; + using OpenSHC::Map::LogicHelpers::L_ROCKY; + using OpenSHC::Map::LogicHelpers::L_WALL_OR_GATEHOUSE; + + // FUNCTION: STRONGHOLDCRUSADER 0x004FF990 + uint TileMapState::returnSomeHeight(int tile, int param_2) + { + int extraHeight = 0; + if ((this->LogicLayer[tile] & L_KEEP_NON_MANOR_HOUSE) != 0) { + return this->HeightLayer[tile] + + MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::getBuildingHeightForBuildingID, + DAT_BuildingsState::ptr)(this->BuildingLayer[tile]); + } + + if ((this->LogicLayer[tile] & L_BUILDING) != 0) { + short buildingID = this->BuildingLayer[tile]; + switch (DAT_BuildingsState::instance.buildings[buildingID].buildingType) { + case OpenSHC::Map::Buildings::BT_GATEHOUSELARGE: + case OpenSHC::Map::Buildings::BT_GATEHOUSESMALL: + case OpenSHC::Map::Buildings::BT_TOWER: + 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 this->HeightLayer[tile] + + MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::getBuildingHeightForBuildingID, + DAT_BuildingsState::ptr)(buildingID) + + 10; + case OpenSHC::Map::Buildings::BT_HUNTERSHUT: + if (param_2 != 0) { + return this->HeightLayer[tile]; + } + default: + return this->HeightLayer[tile] + + DAT_BuildingDefinedData::instance + .BuildingHeights[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: + return this->HeightLayer[tile] + + MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::getBuildingHeightForBuildingID, + DAT_BuildingsState::ptr)(buildingID); + } + } + + /* + OrganismLayer holds tree ids below 2000 and rock ids biased by 2000; Ghidra rendered the + rock lookup as an out-of-bounds index into trees[0x636]. + */ + if ((this->LogicLayer[tile] & L_ROCKY) != 0 && (this->LogicLayer[tile] & L_WALL_OR_GATEHOUSE) == 0 + && this->OrganismLayer[tile] >= 2000) { + short rockType = DAT_LandscapeState::instance.rocks[this->OrganismLayer[tile] - 2000].type; + if (rockType >= 0xd) { + return this->HeightLayer[tile] + 0x46; + } + if (rockType >= 9) { + extraHeight = 0x32; + } + } + return this->HeightLayer[tile] + extraHeight; + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/rotateFearFactorBuildingVariations.cpp b/src/OpenSHC/Map/TileMapState/rotateFearFactorBuildingVariations.cpp new file mode 100644 index 0000000000..bf4a5b4bc2 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/rotateFearFactorBuildingVariations.cpp @@ -0,0 +1,96 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Commands/MappersEnum.hpp" + +#include "OpenSHC/Globals/DAT_TileMapState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Commands::MappersEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x004F8300 + void TileMapState::rotateFearFactorBuildingVariations() + { + /* + currentMapperCommand is reached through the global instance's absolute address, and the + switch below is the original's byte table at 0x004F847C into the jump table at 0x004F8454, + biased by M_MAPPER_GARDEN1. The "- 1 & 6" forms are the original's setcc/dec/and idiom. + */ + DWORD now = timeGetTime(); + if (this->editorRockType == 5) { + if (this->rockOrientation == 0) { + this->rockOrientation = 2; + } else if (this->rockOrientation == 2) { + this->rockOrientation = 4; + } else { + this->rockOrientation = (this->rockOrientation != 4) - 1 & 6; + } + } + if ((int)now < (int)(this->lastTime + 1000)) { + return; + } + + this->lastTime = now; + this->gateOrientationVariant = (this->gateOrientationVariant == 0x50) + 0x50; + if (this->editorRockType == 0) { + if (this->rockOrientation == 0) { + this->rockOrientation = 2; + } else if (this->rockOrientation == 2) { + this->rockOrientation = 4; + } else { + this->rockOrientation = (this->rockOrientation != 4) - 1 & 6; + } + } + + switch (DAT_TileMapState::instance.currentMapperCommand) { + case OpenSHC::Commands::M_MAPPER_GARDEN1: + case OpenSHC::Commands::M_MAPPER_GARDEN2: + case OpenSHC::Commands::M_MAPPER_GARDEN3: + case OpenSHC::Commands::M_MAPPER_GARDEN4: + case OpenSHC::Commands::M_MAPPER_GARDEN5: + case OpenSHC::Commands::M_MAPPER_GARDEN7: + case OpenSHC::Commands::M_MAPPER_GARDEN8: + case OpenSHC::Commands::M_MAPPER_GARDEN10: + case OpenSHC::Commands::M_MAPPER_GARDEN11: + case OpenSHC::Commands::M_MAPPER_CESS_PIT1: + case OpenSHC::Commands::M_MAPPER_CESS_PIT2: + case OpenSHC::Commands::M_MAPPER_CESS_PIT3: + case OpenSHC::Commands::M_MAPPER_STATUE1: + case OpenSHC::Commands::M_MAPPER_STATUE2: + case OpenSHC::Commands::M_MAPPER_STATUE3: + case OpenSHC::Commands::M_MAPPER_STATUE4: + case OpenSHC::Commands::M_MAPPER_SHRINE1: + case OpenSHC::Commands::M_MAPPER_POND1: + case OpenSHC::Commands::M_MAPPER_POND3_LARGE1: + DAT_TileMapState::instance.currentMapperCommand = (MappersEnum)(DAT_TileMapState::instance.currentMapperCommand + OpenSHC::Commands::M_MAPPER_AREA); + return; + case OpenSHC::Commands::M_MAPPER_GARDEN6: + DAT_TileMapState::instance.currentMapperCommand = OpenSHC::Commands::M_MAPPER_GARDEN1; + return; + case OpenSHC::Commands::M_MAPPER_GARDEN9: + DAT_TileMapState::instance.currentMapperCommand = OpenSHC::Commands::M_MAPPER_GARDEN7; + return; + case OpenSHC::Commands::M_MAPPER_GARDEN12: + DAT_TileMapState::instance.currentMapperCommand = OpenSHC::Commands::M_MAPPER_GARDEN10; + return; + case OpenSHC::Commands::M_MAPPER_STATUE5: + DAT_TileMapState::instance.currentMapperCommand = OpenSHC::Commands::M_MAPPER_STATUE1; + return; + case OpenSHC::Commands::M_MAPPER_POND2_SMALL: + DAT_TileMapState::instance.currentMapperCommand = OpenSHC::Commands::M_MAPPER_POND1; + return; + case OpenSHC::Commands::M_MAPPER_POND4_LARGE2: + DAT_TileMapState::instance.currentMapperCommand = OpenSHC::Commands::M_MAPPER_POND3_LARGE1; + return; + case OpenSHC::Commands::M_MAPPER_SHRINE2: + DAT_TileMapState::instance.currentMapperCommand = OpenSHC::Commands::M_MAPPER_SHRINE1; + return; + case OpenSHC::Commands::M_MAPPER_CESS_PIT4: + DAT_TileMapState::instance.currentMapperCommand = OpenSHC::Commands::M_MAPPER_CESS_PIT1; + return; + } + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/setBitFlagBasedOnWallTowerGatehouseOrKeep.cpp b/src/OpenSHC/Map/TileMapState/setBitFlagBasedOnWallTowerGatehouseOrKeep.cpp new file mode 100644 index 0000000000..f5c924a4a8 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/setBitFlagBasedOnWallTowerGatehouseOrKeep.cpp @@ -0,0 +1,37 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Rendering/ViewportRenderState.func.hpp" +#include "OpenSHC/Map/TileMapState/NeighbourFlagsAsm.hpp" + +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +#define NEIGHBOUR_FLAGS_MASK_WALL_OR_KEEP 0x10000100 // L_WALL_OR_GATEHOUSE | L_KEEP_NON_MANOR_HOUSE + +namespace OpenSHC { +namespace Map { + + // FUNCTION: STRONGHOLDCRUSADER 0x004FF870 + byte TileMapState::setBitFlagBasedOnWallTowerGatehouseOrKeep(int x, int y) + { + /* + The body is the handwritten neighbour-flag macro; see NeighbourFlagsAsm.hpp. Written as C++ + it would be: + + this->bitFlag = 0; + if ((this->ptr_LogicLayer[this->DAT_SomeTile + 1] & (L_WALL_OR_GATEHOUSE | L_KEEP_NON_MANOR_HOUSE)) != 0) { + this->bitFlag = 0x20; + } + ... and so on for the eight neighbours, where the north row is offset by + ptr_MovementDirectionTranslationMatrix[DAT_SomeY * 8 + 0] and the south row by [+ 4]. + */ + this->DAT_SomeY = y; + this->DAT_SomeTile = MACRO_CALL_MEMBER( + OpenSHC::Rendering::ViewportRenderState_Func::translateXYToTile, DAT_ViewportRenderState::ptr)(x, y); + + MACRO_NEIGHBOUR_FLAGS_LOGIC_8(1, NEIGHBOUR_FLAGS_MASK_WALL_OR_KEEP) + + return this->bitFlag; + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/setChangedLayerToThreeAndMapping0x40x40.cpp b/src/OpenSHC/Map/TileMapState/setChangedLayerToThreeAndMapping0x40x40.cpp new file mode 100644 index 0000000000..4e41e3e7e0 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/setChangedLayerToThreeAndMapping0x40x40.cpp @@ -0,0 +1,24 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/IO/LowLevelMemory.func.hpp" +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" +#include "OpenSHC/OS.func.hpp" + +#include "OpenSHC/Globals/DAT_LowLevelMemory.hpp" +#include "OpenSHC/Globals/DAT_PathFindingState.hpp" + +namespace OpenSHC { +namespace Map { + + // FUNCTION: STRONGHOLDCRUSADER 0x004F6AE0 + void TileMapState::setChangedLayerToThreeAndMapping0x40x40() + { + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + sizeof(this->ChangedLayer), 3, this->ChangedLayer); + MACRO_CALL(OpenSHC::OS_Func::_memset)(this->mapping40x40, 3, sizeof(this->mapping40x40)); + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::setChangedLayerZeroBasedOn40x40Layer, + DAT_PathFindingState::ptr)(1); + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/setConstructionGFXLayerBasedOnPlacementChecks.cpp b/src/OpenSHC/Map/TileMapState/setConstructionGFXLayerBasedOnPlacementChecks.cpp new file mode 100644 index 0000000000..79c18caee5 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/setConstructionGFXLayerBasedOnPlacementChecks.cpp @@ -0,0 +1,779 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Map/Buildings/BuildingsState.func.hpp" +#include "OpenSHC/Commands/MappersEnum.hpp" +#include "OpenSHC/Map/Buildings/BuildingType.hpp" +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +#include "OpenSHC/Globals/DAT_BuildingDefinedData.hpp" +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_GameState.hpp" +#include "OpenSHC/Globals/DAT_GameSynchronyState.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" +#include "OpenSHC/Globals/GMTotalPicturesProcessed.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Commands::MappersEnum; + using OpenSHC::Map::Buildings::BuildingType; + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x00504F10 + int TileMapState::setConstructionGFXLayerBasedOnPlacementChecks(int x, int y, MappersEnum type, int size) + { + int iVar1; + BuildingType BVar2; + undefined2 uVar8; + int iVar3; + int iVar4; + int iVar5; + int iVar6; + int iVar7; + ushort uVar9; + MappersEnum MVar10; + XYPair* pXVar11; + int* piVar12; + int iVar13; + int iVar14; + int iVar15; + int local_14; + int _offset; + short sprite; + short command; + iVar1 = x; + command = (short)type; + iVar14 = this->skipPlacementFailChecks; + local_14 = 0; + this->skipPlacementFailChecks = 0; + if (iVar14 != 0) { + BVar2 = MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::convertCommandBuildingTypeToBuildingType, + DAT_BuildingsState::ptr)((MappersEnum)command); + this->buildingSpriteSheetID_1 + = DAT_BuildingDefinedData::instance.Building_SpriteSheet_ID_Array_1[BVar2].intValue; + this->buildingSpriteID1 = MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::getSpriteID, + DAT_BuildingsState::ptr)((MappersEnum)command); + this->buildingSpriteID2 = MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::getSpriteID2, + DAT_BuildingsState::ptr)((MappersEnum)command); + } else { + if (this->buildingPlacementFail == 2) { + this->skipPlacementFailChecks = 0; + return (int)(2); + } + if (this->buildingPlacementFail != FALSE) { + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)( + local_14, size); + iVar14 = DAT_ViewportRenderState::instance.translationMatrix[this->buildingY + y].addXgetTile + + this->buildingX + x; + if ((this->LogicLayer[iVar14] & 0x10000500U) == 0) { + iVar15 = MACRO_CALL_MEMBER( + OpenSHC::Map::TileMapState_Func::isBuildingPlacementAllowedAtTile, this)(iVar14, + (int)(DAT_GameSynchronyState::instance.currentPlayerSlotID), (MappersEnum)command, 0); + this->ConstructionGFXLayer[iVar14] = (-(ushort)(iVar15 != 0) & 0xfff9) + 0x3e; + } + local_14 = local_14 + 1; + } while (local_14 < this->constructionTileCount); + uVar8 = (undefined2)((uint)local_14 >> 0x10); + if (command == OpenSHC::Commands::M_MAPPER_KEEP1 || command == OpenSHC::Commands::M_MAPPER_KEEP2 + || command == OpenSHC::Commands::M_MAPPER_KEEP3) { + piVar12 = (int*)((int)DAT_TerrainDefinedData::ptr + ((short)command + -0x3c) * 0x60 + 0x264); + x = 3; + do { + iVar14 = DAT_ViewportRenderState::instance.translationMatrix[piVar12[1] + y].addXgetTile + + *piVar12 + iVar1; + if ((this->LogicLayer[iVar14] & 0x10000500U) == 0) { + iVar15 = MACRO_CALL_MEMBER( + OpenSHC::Map::TileMapState_Func::isBuildingPlacementAllowedAtTile, this)(iVar14, + (int)(DAT_GameSynchronyState::instance.currentPlayerSlotID), (MappersEnum)command, 0); + this->ConstructionGFXLayer[iVar14] = (-(ushort)(iVar15 != 0) & 0xfff9) + 0x3e; + } + piVar12 = piVar12 + 2; + x = x + -1; + } while (x != 0); + iVar3 = ((short)command + -0x3c) * 0x20; + iVar14 = *(int*)((int)DAT_TerrainDefinedData::ptr + iVar3 + 900); + iVar15 = *(int*)((int)DAT_TerrainDefinedData::ptr + iVar3 + 0x388); + local_14 = 0; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)( + local_14, 7); + iVar13 = DAT_ViewportRenderState::instance.translationMatrix[this->buildingY + y + iVar15] + .addXgetTile + + this->buildingX + iVar1 + iVar14; + if ((this->LogicLayer[iVar13] & 0x10000500U) == 0) { + iVar4 = MACRO_CALL_MEMBER( + OpenSHC::Map::TileMapState_Func::isBuildingPlacementAllowedAtTile, this)(iVar13, + (int)(DAT_GameSynchronyState::instance.currentPlayerSlotID), (MappersEnum)command, 0); + this->ConstructionGFXLayer[iVar13] = (-(ushort)(iVar4 != 0) & 0xfff9) + 0x3e; + } + local_14 = local_14 + 1; + } while (local_14 < this->constructionTileCount); + iVar14 = *(int*)((int)DAT_TerrainDefinedData::ptr + iVar3 + 0x3e4); + iVar15 = *(int*)((int)DAT_TerrainDefinedData::ptr + iVar3 + 1000); + iVar3 = 0; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)( + iVar3, 5); + iVar13 = this->buildingY + iVar15 + y; + iVar4 = DAT_ViewportRenderState::instance.translationMatrix[iVar13].addXgetTile + + this->buildingX + iVar14 + iVar1; + if ((this->LogicLayer[iVar4] & 0x10000500U) == 0) { + iVar13 = MACRO_CALL_MEMBER( + OpenSHC::Map::TileMapState_Func::isBuildingPlacementAllowedAtTile, this)(iVar4, + (int)(DAT_GameSynchronyState::instance.currentPlayerSlotID), (MappersEnum)command, 0); + iVar13 = (-(uint)(iVar13 != 0) & 0xfffffff9) + 0x3e; + this->ConstructionGFXLayer[iVar4] = (ushort)iVar13; + } + uVar8 = (undefined2)((uint)iVar13 >> 0x10); + iVar3 = iVar3 + 1; + } while (iVar3 < this->constructionTileCount); + } + if (command == OpenSHC::Commands::M_MAPPER_GATE_WOOD1A + || command == OpenSHC::Commands::M_MAPPER_GATE_WOOD1B + || command == OpenSHC::Commands::M_MAPPER_GATE_WOOD1C + || command == OpenSHC::Commands::M_MAPPER_GATE_WOOD1D) { + MVar10 = (MappersEnum)command; + iVar14 = MVar10 * 3 + -0x1a4; + iVar15 = *(int*)((int)DAT_TerrainDefinedData::ptr + iVar14 * 8 + 0x56c); + iVar14 = iVar14 * 8; + iVar3 = *(int*)((int)DAT_TerrainDefinedData::ptr + iVar14 + 0x570); + iVar13 = 0; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)( + iVar13, 3); + iVar5 = DAT_ViewportRenderState::instance.translationMatrix[this->buildingY + iVar3 + y] + .addXgetTile + + this->buildingX + iVar15 + iVar1; + iVar4 = MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::isBuildingPlacementAllowedAtTile, + this)(iVar5, (int)(DAT_GameSynchronyState::instance.currentPlayerSlotID), MVar10, 0); + iVar13 = iVar13 + 1; + this->ConstructionGFXLayer[iVar5] = (-(ushort)(iVar4 != 0) & 0xfff9) + 0x3e; + } while (iVar13 < this->constructionTileCount); + iVar15 = *(int*)((int)DAT_TerrainDefinedData::ptr + iVar14 + 0x578); + iVar14 = *(int*)((int)DAT_TerrainDefinedData::ptr + iVar14 + 0x57c); + iVar3 = 0; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)( + iVar3, 3); + iVar4 = DAT_ViewportRenderState::instance.translationMatrix[this->buildingY + iVar14 + y] + .addXgetTile + + this->buildingX + iVar15 + iVar1; + iVar13 = MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::isBuildingPlacementAllowedAtTile, + this)(iVar4, (int)(DAT_GameSynchronyState::instance.currentPlayerSlotID), MVar10, 0); + iVar3 = iVar3 + 1; + this->ConstructionGFXLayer[iVar4] = (-(ushort)(iVar13 != 0) & 0xfff9) + 0x3e; + } while (iVar3 < this->constructionTileCount); + piVar12 = (int*)((int)DAT_TerrainDefinedData::ptr + (MVar10 * 3 + -0x1a4) * 0x10 + 0x5cc); + type = OpenSHC::Commands::M_MAPPER_FOREST; + do { + iVar15 = DAT_ViewportRenderState::instance.translationMatrix[piVar12[1] + y].addXgetTile + + *piVar12 + iVar1; + iVar14 = MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::isBuildingPlacementAllowedAtTile, + this)(iVar15, (int)(DAT_GameSynchronyState::instance.currentPlayerSlotID), MVar10, 0); + iVar14 = (-(uint)(iVar14 != 0) & 0xfffffff9) + 0x3e; + piVar12 = piVar12 + 2; + type = (MappersEnum)(type - OpenSHC::Commands::M_MAPPER_AREA); + this->ConstructionGFXLayer[iVar15] = (ushort)iVar14; + } while (type != OpenSHC::Commands::M_MAPPER_NULL); + return iVar14; + } + if ((command == OpenSHC::Commands::M_MAPPER_BARRACKS_EURO) + || (command == OpenSHC::Commands::M_MAPPER_BARRACKS_ARAB)) { + iVar14 = 0; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)( + iVar14, 5); + iVar3 = this->buildingX; + iVar15 = DAT_ViewportRenderState::instance.translationMatrix[this->buildingY + y].addXgetTile; + if ((this->LogicLayer[iVar1 + this->buildingX + iVar15 + 5] & 0x10000500U) == 0) { + iVar13 = MACRO_CALL_MEMBER( + OpenSHC::Map::TileMapState_Func::isBuildingPlacementAllowedAtTile, this)( + iVar15 + this->buildingX + iVar1 + 5, + (int)(DAT_GameSynchronyState::instance.currentPlayerSlotID), (MappersEnum)command, 0); + this->ConstructionGFXLayer[iVar1 + iVar3 + iVar15 + 5] + = (-(ushort)(iVar13 != 0) & 0xfff9) + 0x3e; + } + iVar14 = iVar14 + 1; + } while (iVar14 < this->constructionTileCount); + iVar14 = 0; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)( + iVar14, 5); + iVar15 + = DAT_ViewportRenderState::instance.translationMatrix[y + this->buildingY + 5].addXgetTile + + this->buildingX + iVar1; + if ((this->LogicLayer[iVar15] & 0x10000500U) == 0) { + iVar3 = MACRO_CALL_MEMBER( + OpenSHC::Map::TileMapState_Func::isBuildingPlacementAllowedAtTile, this)(iVar15, + (int)(DAT_GameSynchronyState::instance.currentPlayerSlotID), (MappersEnum)command, 0); + this->ConstructionGFXLayer[iVar15] = (-(ushort)(iVar3 != 0) & 0xfff9) + 0x3e; + } + iVar14 = iVar14 + 1; + } while (iVar14 < this->constructionTileCount); + iVar14 = 0; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)( + iVar14, 5); + iVar3 = this->buildingX; + iVar13 = this->buildingY + y + 5; + iVar15 + = DAT_ViewportRenderState::instance.translationMatrix[y + this->buildingY + 5].addXgetTile; + if ((this->LogicLayer[iVar1 + this->buildingX + iVar15 + 5] & 0x10000500U) == 0) { + iVar13 = MACRO_CALL_MEMBER( + OpenSHC::Map::TileMapState_Func::isBuildingPlacementAllowedAtTile, this)( + iVar15 + this->buildingX + iVar1 + 5, + (int)(DAT_GameSynchronyState::instance.currentPlayerSlotID), (MappersEnum)command, 0); + iVar13 = (-(uint)(iVar13 != 0) & 0xfffffff9) + 0x3e; + this->ConstructionGFXLayer[iVar1 + iVar3 + iVar15 + 5] = (ushort)iVar13; + } + iVar14 = iVar14 + 1; + } while (iVar14 < this->constructionTileCount); + return iVar13; + } + if ((command != OpenSHC::Commands::M_MAPPER_ENGINEERS_GUILD) + && (command != OpenSHC::Commands::M_MAPPER_TUNNELERS_GUILD)) { + if (command != OpenSHC::Commands::M_MAPPER_OIL_SMELTER) { + /* the original returns eax with a leftover tile index still in its high half */ + return (ushort)command; + } + iVar14 = 0; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)( + iVar14, 4); + iVar15 = this->buildingY + y + 4; + iVar3 = DAT_ViewportRenderState::instance.translationMatrix[y + this->buildingY + 4].addXgetTile + + this->buildingX + iVar1; + if ((this->LogicLayer[iVar3] & 0x10000500U) == 0) { + iVar15 + = MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::isBuildingPlacementAllowedAtTile, + this)(iVar3, (int)(DAT_GameSynchronyState::instance.currentPlayerSlotID), + OpenSHC::Commands::M_MAPPER_OIL_SMELTER, 0); + iVar15 = (-(uint)(iVar15 != 0) & 0xfffffff9) + 0x3e; + this->ConstructionGFXLayer[iVar3] = (ushort)iVar15; + } + iVar14 = iVar14 + 1; + } while (iVar14 < this->constructionTileCount); + return iVar15; + } + iVar14 = 0; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)( + iVar14, 5); + iVar15 = (this->buildingY + y + 5) * 3; + iVar3 = DAT_ViewportRenderState::instance.translationMatrix[y + this->buildingY + 5].addXgetTile + + this->buildingX + iVar1; + if ((this->LogicLayer[iVar3] & 0x10000500U) == 0) { + iVar15 = MACRO_CALL_MEMBER( + OpenSHC::Map::TileMapState_Func::isBuildingPlacementAllowedAtTile, this)(iVar3, + (int)(DAT_GameSynchronyState::instance.currentPlayerSlotID), (MappersEnum)command, 0); + iVar15 = (-(uint)(iVar15 != 0) & 0xfffffff9) + 0x3e; + this->ConstructionGFXLayer[iVar3] = (ushort)iVar15; + } + iVar14 = iVar14 + 1; + } while (iVar14 < this->constructionTileCount); + return iVar15; + } + } + if (command == OpenSHC::Commands::M_MAPPER_WHEATFARM) { + size = 3; + } else if (command == OpenSHC::Commands::M_MAPPER_HOPSFARM) { + size = 3; + } else if (command == OpenSHC::Commands::M_MAPPER_APPLEFARM) { + size = 3; + } else if (command == OpenSHC::Commands::M_MAPPER_CATTLEFARM) { + size = 3; + } else if (command == OpenSHC::Commands::M_MAPPER_GATE_WOOD1A + || command == OpenSHC::Commands::M_MAPPER_GATE_WOOD1C || command == OpenSHC::Commands::M_MAPPER_GATE_STONE1A + || command == OpenSHC::Commands::M_MAPPER_GATE_STONE2A) { + this->gateOrientationVariant = 0x51; + } else if (command == OpenSHC::Commands::M_MAPPER_GATE_WOOD1B + || command == OpenSHC::Commands::M_MAPPER_GATE_WOOD1D || command == OpenSHC::Commands::M_MAPPER_GATE_STONE1B + || command == OpenSHC::Commands::M_MAPPER_GATE_STONE2B) { + this->gateOrientationVariant = 0x50; + } + MVar10 = (MappersEnum)command; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)(local_14, size); + iVar3 = DAT_ViewportRenderState::instance.translationMatrix[this->buildingY + y].addXgetTile + + this->buildingX + iVar1; + iVar15 = this->uiBuildingRotation; + if (this->uiBuildingRotation != 0xf && this->uiBuildingRotation != 8 + && (iVar15 = this->uiBuildingRotation - this->mapOrientation, iVar15 < 0)) { + iVar15 = iVar15 + 8; + } + sprite = (short)this->buildingSpriteID1; + if ((this->mapOrientation == 2) || (this->mapOrientation == 6)) { + if (this->gateOrientationVariant != 0x51) + goto LAB_00505714; + } else if (this->gateOrientationVariant == 0x51) { + LAB_00505714: + sprite = (short)this->buildingSpriteID2; + } + if ((command == OpenSHC::Commands::M_MAPPER_DRAWBRIDGE) && (iVar15 != 0)) { + if (iVar15 == 2) { + iVar15 = 3; + } else if (iVar15 == 4) { + iVar15 = 2; + } else if (iVar15 == 6) { + iVar15 = 1; + } + } + BVar2 = MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::convertCommandBuildingTypeToBuildingType, + DAT_BuildingsState::ptr)(MVar10); + if (BVar2 == OpenSHC::Map::Buildings::BT_UNKNOWN1) { + sprite = sprite + (short)(&DAT_BuildingDefinedData::instance.field209_0x976c[9].y)[MVar10]; + } else { + BVar2 = MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::convertCommandBuildingTypeToBuildingType, + DAT_BuildingsState::ptr)(MVar10); + if (BVar2 == OpenSHC::Map::Buildings::BT_HOVEL) { + sprite = (short)DAT_BuildingDefinedData::instance.SomeSpriteArray1[DAT_GameState::instance + .playerDataArray[DAT_GameSynchronyState::instance.currentPlayerSlotID] + .hovelCountUpToEight]; + } + } + if (this->uiBuildingRotation == 0xf) { + this->ConstructionGFXLayer[iVar3] + = ((short)GMTotalPicturesProcessed::instance[this->buildingSpriteSheetID_1] + sprite + + (short)this->buildingRotationRelatedValue) + - 1; + } else { + this->ConstructionGFXLayer[iVar3] + = ((short)(iVar15 * size * size) + + (short)GMTotalPicturesProcessed::instance[this->buildingSpriteSheetID_1] + sprite + + (short)this->buildingRotationRelatedValue) + - 1; + } + if (iVar14 != 0) { + this->MiscDisplayLayer[iVar3] = this->MiscDisplayLayer[iVar3] | 0x8000; + } + local_14 = local_14 + 1; + if (this->constructionTileCount <= local_14) { + iVar15 = (ushort)command; + if (command == OpenSHC::Commands::M_MAPPER_GATE_WOOD1A + || command == OpenSHC::Commands::M_MAPPER_GATE_WOOD1B + || command == OpenSHC::Commands::M_MAPPER_GATE_WOOD1C + || command == OpenSHC::Commands::M_MAPPER_GATE_WOOD1D) { + /* + 0 3 6 9 + */ + _offset = MVar10 * 3 + -420; + iVar15 = *(int*)((int)DAT_TerrainDefinedData::ptr + _offset * 8 + 0x50c); + iVar3 = *(int*)((int)DAT_TerrainDefinedData::ptr + _offset * 8 + 0x510); + /* + 0 24 48 72 + */ + iVar4 = _offset * 8; + iVar13 = *(int*)((int)DAT_TerrainDefinedData::ptr + iVar4 + 0x514); + iVar5 = 0; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)( + iVar5, 2); + iVar6 = DAT_ViewportRenderState::instance.translationMatrix[iVar3 + y + this->buildingY] + .addXgetTile + + this->buildingX + iVar15 + iVar1; + this->ConstructionGFXLayer[iVar6] = (short)this->buildingRotationRelatedValue + + (short)GMTotalPicturesProcessed::instance[0x34]; + if (iVar14 != 0) { + this->MiscDisplayLayer[iVar6] = this->MiscDisplayLayer[iVar6] | 0x8000; + } + iVar5 = iVar5 + 1; + } while (iVar5 < this->constructionTileCount); + pXVar11 = &DAT_TerrainDefinedData::instance.field555_0x68c + iVar13 * 5; + iVar5 = 0; + do { + iVar6 = DAT_ViewportRenderState::instance.translationMatrix[pXVar11->y + iVar3 + y].addXgetTile + + pXVar11->x + iVar15 + iVar1; + if (iVar5 < 1) { + this->ConstructionGFXLayer[iVar6] + = (short)GMTotalPicturesProcessed::instance[0x34] + 0x60e + (short)iVar5; + } else { + iVar7 = DAT_TerrainDefinedData::instance.ConstructionSpriteRotationTable[iVar5 + iVar13 * 4] + - this->mapOrientation; + if (iVar7 < 0) { + iVar7 = iVar7 + 8; + } + this->ConstructionGFXLayer[iVar6] = (short)GMTotalPicturesProcessed::instance[0x34] + + (short)(iVar7 / 2) * 4 + 0x60e + (short)iVar5; + } + if (iVar14 != 0) { + this->MiscDisplayLayer[iVar6] = this->MiscDisplayLayer[iVar6] | 0x8000; + } + iVar5 = iVar5 + 1; + pXVar11 = pXVar11 + 1; + } while (iVar5 < 5); + iVar15 = *(int*)((int)DAT_TerrainDefinedData::ptr + iVar4 + 0x518); + iVar3 = *(int*)((int)DAT_TerrainDefinedData::ptr + iVar4 + 0x51c); + iVar13 = *(int*)((int)DAT_TerrainDefinedData::ptr + iVar4 + 0x520); + iVar4 = 0; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)( + iVar4, 2); + iVar5 = DAT_ViewportRenderState::instance.translationMatrix[iVar3 + y + this->buildingY] + .addXgetTile + + this->buildingX + iVar15 + iVar1; + this->ConstructionGFXLayer[iVar5] = (short)this->buildingRotationRelatedValue + + (short)GMTotalPicturesProcessed::instance[0x34]; + if (iVar14 != 0) { + this->MiscDisplayLayer[iVar5] = this->MiscDisplayLayer[iVar5] | 0x8000; + } + iVar4 = iVar4 + 1; + } while (iVar4 < this->constructionTileCount); + pXVar11 = &DAT_TerrainDefinedData::instance.field555_0x68c + iVar13 * 5; + iVar4 = 0; + do { + iVar5 = DAT_ViewportRenderState::instance.translationMatrix[pXVar11->y + iVar3 + y].addXgetTile + + pXVar11->x + iVar15 + iVar1; + if (iVar4 < 1) { + this->ConstructionGFXLayer[iVar5] + = (short)GMTotalPicturesProcessed::instance[0x34] + 0x60e + (short)iVar4; + } else { + iVar6 = DAT_TerrainDefinedData::instance.ConstructionSpriteRotationTable[iVar4 + iVar13 * 4] + - this->mapOrientation; + if (iVar6 < 0) { + iVar6 = iVar6 + 8; + } + this->ConstructionGFXLayer[iVar5] = (short)GMTotalPicturesProcessed::instance[0x34] + + (short)(iVar6 / 2) * 4 + 0x60e + (short)iVar4; + } + if (iVar14 != 0) { + this->MiscDisplayLayer[iVar5] = this->MiscDisplayLayer[iVar5] | 0x8000; + } + iVar4 = iVar4 + 1; + pXVar11 = pXVar11 + 1; + } while (iVar4 < 5); + piVar12 = (int*)((int)DAT_TerrainDefinedData::ptr + (MVar10 * 3 + -0x1a4) * 0x10 + 0x5cc); + type = OpenSHC::Commands::M_MAPPER_FOREST; + do { + iVar15 = DAT_ViewportRenderState::instance.translationMatrix[piVar12[1] + y].addXgetTile + iVar1 + + *piVar12; + this->ConstructionGFXLayer[iVar15] = ((byte)this->RandomLayer[iVar15] & 3) + 0x138 + + (short)GMTotalPicturesProcessed::instance[6]; + if (iVar14 != 0) { + this->MiscDisplayLayer[iVar15] = this->MiscDisplayLayer[iVar15] | 0x8000; + } + piVar12 = piVar12 + 2; + type = (MappersEnum)(type - OpenSHC::Commands::M_MAPPER_AREA); + } while (type != OpenSHC::Commands::M_MAPPER_NULL); + } else { + if (command == OpenSHC::Commands::M_MAPPER_WHEATFARM) { + iVar15 = 0; + do { + iVar3 = DAT_GameState::instance + .playerDataArray[DAT_GameSynchronyState::instance.currentPlayerSlotID] + .unkWheatFarmOrientation; + iVar3 = DAT_ViewportRenderState::instance + .translationMatrix + [DAT_TerrainDefinedData::instance.WheatFarmTiles[iVar3][iVar15].y + y] + .addXgetTile + + DAT_TerrainDefinedData::instance.WheatFarmTiles[iVar3][iVar15].x + iVar1; + this->ConstructionGFXLayer[iVar3] + = ((byte)this->RandomLayer[iVar3] & 3) + (short)GMTotalPicturesProcessed::instance[0xe]; + if (iVar14 != 0) { + this->MiscDisplayLayer[iVar3] = this->MiscDisplayLayer[iVar3] | 0x8000; + } + iVar15 = iVar15 + 1; + } while (iVar15 < 0x24); + return iVar3; + } + if (command == OpenSHC::Commands::M_MAPPER_HOPSFARM) { + iVar15 = 0; + do { + iVar3 = *(int*)&DAT_GameState::instance + .playerDataArray[DAT_GameSynchronyState::instance.currentPlayerSlotID] + .unkHopFarmVariation; + iVar3 = DAT_ViewportRenderState::instance + .translationMatrix + [DAT_TerrainDefinedData::instance.HopFarmProperty1[iVar3][iVar15].y + y] + .addXgetTile + + DAT_TerrainDefinedData::instance.HopFarmProperty1[iVar3][iVar15].x + iVar1; + this->ConstructionGFXLayer[iVar3] = ((byte)this->RandomLayer[iVar3] & 1) * 9 + 0x25 + + (short)GMTotalPicturesProcessed::instance[0xe]; + if (iVar14 != 0) { + this->MiscDisplayLayer[iVar3] = this->MiscDisplayLayer[iVar3] | 0x8000; + } + iVar15 = iVar15 + 1; + } while (iVar15 < 0x18); + return iVar3; + } + if (command == OpenSHC::Commands::M_MAPPER_CATTLEFARM) { + iVar15 = 0; + do { + iVar3 = DAT_GameState::instance + .playerDataArray[DAT_GameSynchronyState::instance.currentPlayerSlotID] + .dairyFarmVariationMod4; + iVar13 + = DAT_ViewportRenderState::instance + .translationMatrix + [DAT_TerrainDefinedData::instance.field878_0xf5c[iVar3][iVar15 + 4].offset.y + + y] + .addXgetTile + + DAT_TerrainDefinedData::instance.field878_0xf5c[iVar3][iVar15 + 4].offset.x + iVar1; + iVar3 = MACRO_CALL_MEMBER( + OpenSHC::Map::TileMapState_Func::getRubbleGraphicStageForDamageLevel, this)( + DAT_TerrainDefinedData::instance.field878_0xf5c[iVar3][iVar15 + 4].property); + iVar3 = iVar3 + 0x37 + GMTotalPicturesProcessed::instance[0xe]; + this->ConstructionGFXLayer[iVar13] = (ushort)iVar3; + if (iVar14 != 0) { + this->MiscDisplayLayer[iVar13] = this->MiscDisplayLayer[iVar13] | 0x8000; + } + iVar15 = iVar15 + 1; + } while (iVar15 < 0x17); + return iVar3; + } + if (command == OpenSHC::Commands::M_MAPPER_APPLEFARM) { + pXVar11 = DAT_TerrainDefinedData::instance.AppleFarmOffsets; + do { + iVar15 = DAT_ViewportRenderState::instance.translationMatrix[pXVar11->y + y].addXgetTile + + pXVar11->x + iVar1; + this->ConstructionGFXLayer[iVar15] = (short)GMTotalPicturesProcessed::instance[0xe] + 0x3d; + if (iVar14 != 0) { + this->MiscDisplayLayer[iVar15] = this->MiscDisplayLayer[iVar15] | 0x8000; + } + pXVar11 = pXVar11 + 1; + } while ((int)pXVar11 < 0xb49eb0); + return iVar15; + } + if ((command == OpenSHC::Commands::M_MAPPER_BARRACKS_EURO) + || (command == OpenSHC::Commands::M_MAPPER_BARRACKS_ARAB)) { + iVar15 = 0; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)( + iVar15, 5); + iVar13 = this->buildingX; + iVar3 + = DAT_ViewportRenderState::instance.translationMatrix[this->buildingY + y].addXgetTile; + this->ConstructionGFXLayer[iVar1 + this->buildingX + iVar3 + 5] + = (short)this->buildingRotationRelatedValue + + (short)GMTotalPicturesProcessed::instance[6] + 0x48; + if (iVar14 != 0) { + this->MiscDisplayLayer[iVar1 + iVar13 + iVar3 + 5] + = this->MiscDisplayLayer[iVar1 + iVar13 + iVar3 + 5] | 0x8000; + } + iVar15 = iVar15 + 1; + } while (iVar15 < this->constructionTileCount); + iVar15 = 0; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)( + iVar15, 5); + iVar3 = DAT_ViewportRenderState::instance.translationMatrix[y + this->buildingY + 5] + .addXgetTile + + this->buildingX + iVar1; + this->ConstructionGFXLayer[iVar3] = (short)this->buildingRotationRelatedValue + + (short)GMTotalPicturesProcessed::instance[6] + 0x7a; + if (iVar14 != 0) { + this->MiscDisplayLayer[iVar3] = this->MiscDisplayLayer[iVar3] | 0x8000; + } + iVar15 = iVar15 + 1; + } while (iVar15 < this->constructionTileCount); + iVar15 = 0; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)( + iVar15, 5); + iVar13 = this->buildingX; + iVar3 = DAT_ViewportRenderState::instance.translationMatrix[y + this->buildingY + 5] + .addXgetTile; + iVar4 = iVar3 + this->buildingX; + this->ConstructionGFXLayer[iVar1 + this->buildingX + iVar3 + 5] + = (short)this->buildingRotationRelatedValue + + (short)GMTotalPicturesProcessed::instance[6] + 0x61; + if (iVar14 != 0) { + this->MiscDisplayLayer[iVar1 + iVar13 + iVar3 + 5] + = this->MiscDisplayLayer[iVar1 + iVar13 + iVar3 + 5] | 0x8000; + } + iVar15 = iVar15 + 1; + } while (iVar15 < this->constructionTileCount); + return iVar4 + iVar1 + 5; + } + if (command == OpenSHC::Commands::M_MAPPER_ENGINEERS_GUILD) { + iVar15 = 0; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)( + iVar15, 5); + iVar3 = DAT_ViewportRenderState::instance.translationMatrix[y + this->buildingY + 5] + .addXgetTile + + this->buildingX + iVar1; + this->ConstructionGFXLayer[iVar3] = (short)this->buildingRotationRelatedValue + + (short)GMTotalPicturesProcessed::instance[6] + 0x93; + if (iVar14 != 0) { + this->MiscDisplayLayer[iVar3] = this->MiscDisplayLayer[iVar3] | 0x8000; + } + iVar15 = iVar15 + 1; + } while (iVar15 < this->constructionTileCount); + return iVar3; + } + if (command == OpenSHC::Commands::M_MAPPER_TUNNELERS_GUILD) { + iVar15 = 0; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)( + iVar15, 5); + iVar3 = DAT_ViewportRenderState::instance.translationMatrix[y + this->buildingY + 5] + .addXgetTile + + this->buildingX + iVar1; + this->ConstructionGFXLayer[iVar3] = (short)this->buildingRotationRelatedValue + + (short)GMTotalPicturesProcessed::instance[6] + 0xac; + if (iVar14 != 0) { + this->MiscDisplayLayer[iVar3] = this->MiscDisplayLayer[iVar3] | 0x8000; + } + iVar15 = iVar15 + 1; + } while (iVar15 < this->constructionTileCount); + return iVar3; + } + if (command == OpenSHC::Commands::M_MAPPER_OIL_SMELTER) { + iVar15 = 0; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)( + iVar15, 4); + iVar3 = DAT_ViewportRenderState::instance.translationMatrix[y + this->buildingY + 4] + .addXgetTile + + this->buildingX + iVar1; + this->ConstructionGFXLayer[iVar3] = (short)this->buildingRotationRelatedValue + + (short)GMTotalPicturesProcessed::instance[6] + 0x128; + if (iVar14 != 0) { + this->MiscDisplayLayer[iVar3] = this->MiscDisplayLayer[iVar3] | 0x8000; + } + iVar15 = iVar15 + 1; + } while (iVar15 < this->constructionTileCount); + return iVar3; + } + if (command == OpenSHC::Commands::M_MAPPER_KEEP1) { + uVar9 = (ushort)(this->mapOrientation == 2); + iVar15 = DAT_ViewportRenderState::instance + .translationMatrix[DAT_TerrainDefinedData::instance.field130_0x264[0][0].y + y] + .addXgetTile + + DAT_TerrainDefinedData::instance.field130_0x264[0][0].x + iVar1; + this->ConstructionGFXLayer[iVar15] + = (short)GMTotalPicturesProcessed::instance[0x34] + 0x523 + uVar9; + if (iVar14 != 0) { + this->MiscDisplayLayer[iVar15] = this->MiscDisplayLayer[iVar15] | 0x8000; + } + iVar15 = DAT_ViewportRenderState::instance + .translationMatrix[DAT_TerrainDefinedData::instance.field130_0x264[0][1].y + y] + .addXgetTile + + DAT_TerrainDefinedData::instance.field130_0x264[0][1].x + iVar1; + this->ConstructionGFXLayer[iVar15] + = (short)GMTotalPicturesProcessed::instance[0x34] + 0x52e + uVar9; + if (iVar14 != 0) { + this->MiscDisplayLayer[iVar15] = this->MiscDisplayLayer[iVar15] | 0x8000; + } + iVar15 = DAT_ViewportRenderState::instance + .translationMatrix[DAT_TerrainDefinedData::instance.field130_0x264[0][2].y + y] + .addXgetTile + + DAT_TerrainDefinedData::instance.field130_0x264[0][2].x + iVar1; + this->ConstructionGFXLayer[iVar15] + = (short)GMTotalPicturesProcessed::instance[0x34] + 0x527 + uVar9; + if (iVar14 != 0) { + this->MiscDisplayLayer[iVar15] = this->MiscDisplayLayer[iVar15] | 0x8000; + } + iVar3 = iVar1 + DAT_TerrainDefinedData::instance.keepOutbuildingOffsets_0x384[0][0].xOffset; + iVar13 = y + DAT_TerrainDefinedData::instance.keepOutbuildingOffsets_0x384[0][0].yOffset; + iVar15 = 0; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)( + iVar15, 7); + iVar4 = DAT_ViewportRenderState::instance.translationMatrix[this->buildingY + iVar13] + .addXgetTile + + this->buildingX + iVar3; + this->ConstructionGFXLayer[iVar4] = (short)this->buildingRotationRelatedValue + + (short)GMTotalPicturesProcessed::instance[6] + 0x17; + if (iVar14 != 0) { + this->MiscDisplayLayer[iVar4] = this->MiscDisplayLayer[iVar4] | 0x8000; + } + iVar15 = iVar15 + 1; + } while (iVar15 < this->constructionTileCount); + iVar1 = DAT_TerrainDefinedData::instance.keepOutbuildingOffsets_0x3e4[0][0].xOffset + iVar1; + iVar15 = DAT_TerrainDefinedData::instance.keepOutbuildingOffsets_0x3e4[0][0].yOffset + y; + iVar3 = 0; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)( + iVar3, 5); + iVar13 = DAT_ViewportRenderState::instance.translationMatrix[this->buildingY + iVar15] + .addXgetTile + + this->buildingX + iVar1; + this->ConstructionGFXLayer[iVar13] = (short)this->buildingRotationRelatedValue + + (short)GMTotalPicturesProcessed::instance[7] + 0x19; + if (iVar14 != 0) { + this->MiscDisplayLayer[iVar13] = this->MiscDisplayLayer[iVar13] | 0x8000; + } + iVar3 = iVar3 + 1; + } while (iVar3 < this->constructionTileCount); + return iVar13; + } + if ((command == OpenSHC::Commands::M_MAPPER_KEEP2) + || (command == OpenSHC::Commands::M_MAPPER_KEEP3)) { + uVar9 = (ushort)(this->mapOrientation == 2); + iVar15 = (MVar10 - OpenSHC::Commands::M_MAPPER_KEEP1) * 0x60; + iVar3 = DAT_ViewportRenderState::instance + .translationMatrix[*(int*)((int)DAT_TerrainDefinedData::ptr + iVar15 + 0x268) + y] + .addXgetTile + + *(int*)((int)DAT_TerrainDefinedData::ptr + iVar15 + 0x264) + iVar1; + this->ConstructionGFXLayer[iVar3] + = (short)GMTotalPicturesProcessed::instance[0x34] + 0x521 + uVar9; + if (iVar14 != 0) { + this->MiscDisplayLayer[iVar3] = this->MiscDisplayLayer[iVar3] | 0x8000; + } + iVar3 = DAT_ViewportRenderState::instance + .translationMatrix[*(int*)((int)DAT_TerrainDefinedData::ptr + iVar15 + 0x270) + y] + .addXgetTile + + *(int*)((int)DAT_TerrainDefinedData::ptr + iVar15 + 0x26c) + iVar1; + this->ConstructionGFXLayer[iVar3] + = (short)GMTotalPicturesProcessed::instance[0x34] + 0x529 + uVar9; + if (iVar14 != 0) { + this->MiscDisplayLayer[iVar3] = this->MiscDisplayLayer[iVar3] | 0x8000; + } + iVar15 = DAT_ViewportRenderState::instance + .translationMatrix[*(int*)((int)DAT_TerrainDefinedData::ptr + iVar15 + 0x278) + y] + .addXgetTile + + *(int*)((int)DAT_TerrainDefinedData::ptr + iVar15 + 0x274) + iVar1; + this->ConstructionGFXLayer[iVar15] + = (short)GMTotalPicturesProcessed::instance[0x34] + 0x525 + uVar9; + if (iVar14 != 0) { + this->MiscDisplayLayer[iVar15] = this->MiscDisplayLayer[iVar15] | 0x8000; + } + iVar13 = (MVar10 - OpenSHC::Commands::M_MAPPER_KEEP1) * 0x20; + iVar15 = *(int*)((int)DAT_TerrainDefinedData::ptr + iVar13 + 900); + iVar3 = *(int*)((int)DAT_TerrainDefinedData::ptr + iVar13 + 0x388); + iVar4 = 0; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)( + iVar4, 7); + iVar5 = DAT_ViewportRenderState::instance.translationMatrix[this->buildingY + y + iVar3] + .addXgetTile + + this->buildingX + iVar1 + iVar15; + this->ConstructionGFXLayer[iVar5] = (short)this->buildingRotationRelatedValue + + (short)GMTotalPicturesProcessed::instance[6] + 0x17; + if (iVar14 != 0) { + this->MiscDisplayLayer[iVar5] = this->MiscDisplayLayer[iVar5] | 0x8000; + } + iVar4 = iVar4 + 1; + } while (iVar4 < this->constructionTileCount); + iVar15 = *(int*)((int)DAT_TerrainDefinedData::ptr + iVar13 + 0x3e4); + iVar3 = *(int*)((int)DAT_TerrainDefinedData::ptr + iVar13 + 1000); + iVar13 = 0; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)( + iVar13, 5); + iVar4 = DAT_ViewportRenderState::instance.translationMatrix[this->buildingY + iVar3 + y] + .addXgetTile + + this->buildingX + iVar15 + iVar1; + this->ConstructionGFXLayer[iVar4] = (short)this->buildingRotationRelatedValue + + (short)GMTotalPicturesProcessed::instance[7] + 0x19; + if (iVar14 != 0) { + this->MiscDisplayLayer[iVar4] = this->MiscDisplayLayer[iVar4] | 0x8000; + } + iVar13 = iVar13 + 1; + } while (iVar13 < this->constructionTileCount); + return iVar4; + } + } + return iVar15; + } + } while (true); + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/setLand.cpp b/src/OpenSHC/Map/TileMapState/setLand.cpp new file mode 100644 index 0000000000..eef3d2f2a4 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/setLand.cpp @@ -0,0 +1,85 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" + +#include "OpenSHC/Globals/DAT_PathFindingState.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L2_PLATEAU_HIGH; + using OpenSHC::Map::LogicHelpers::L2_PLATEAU_MEDIUM; + using OpenSHC::Map::LogicHelpers::L_BORDER; + using OpenSHC::Map::LogicHelpers::L_BORDER_EDGE; + using OpenSHC::Map::LogicHelpers::L_BUILDING; + using OpenSHC::Map::LogicHelpers::L_CLIMBABLE; + using OpenSHC::Map::LogicHelpers::L_DEFAULT_EARTH_OR_TEXTURE; + using OpenSHC::Map::LogicHelpers::L_FARM_FIELD_APPLE; + using OpenSHC::Map::LogicHelpers::L_FARM_FIELD_DAIRY; + using OpenSHC::Map::LogicHelpers::L_FARM_FIELD_HOP; + using OpenSHC::Map::LogicHelpers::L_FARM_FIELD_WHEAT; + using OpenSHC::Map::LogicHelpers::L_KEEP_NON_MANOR_HOUSE; + using OpenSHC::Map::LogicHelpers::L_MOAT; + using OpenSHC::Map::LogicHelpers::L_MOAT_DUG_OR_PLANNED; + using OpenSHC::Map::LogicHelpers::L_PLAIN1_AND_FARM; + using OpenSHC::Map::LogicHelpers::L_ROCKY; + using OpenSHC::Map::LogicHelpers::L_STOCKPILEUnk; + using OpenSHC::Map::LogicHelpers::L_TREE; + using OpenSHC::Map::LogicHelpers::L_UNKNOWN_WALL_RELATED; + using OpenSHC::Map::LogicHelpers::L_WALL_OR_GATEHOUSE; + + // FUNCTION: STRONGHOLDCRUSADER 0x00502390 + void TileMapState::setLand(int tile, uint y, uint brushType) + { + int baseTile = tile; + int brushSize = DAT_TerrainDefinedData::instance.BrushSizeArray[brushType]; + uint baseY = y; + int index = 0; + if (brushSize > 0) { + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getTileForBrush, this)( + 1, index, &tile, (int*)&y, baseTile, baseY); + if ((this->LogicLayer[tile] & (L_BORDER | L_BORDER_EDGE)) == 0 + && (this->LogicLayer[tile] & (L_WALL_OR_GATEHOUSE | L_BUILDING | L_KEEP_NON_MANOR_HOUSE)) == 0 + && this->BuildingLayer[tile] == 0 && (this->LogicLayer[tile] & L_TREE) == 0 + && ((this->LogicLayer[tile] & L_ROCKY) == 0 || this->OrganismLayer[tile] == 0)) { + if (this->DefaultHeightLayer[tile] < 8) { + this->DefaultHeightLayer[tile] = 8; + } + this->HeightLayer[tile] = this->DefaultHeightLayer[tile]; + this->MiscDisplayLayer[tile] = this->MiscDisplayLayer[tile] & 0xffdf; + if ((this->LogicLayer[tile] & (L_MOAT | L_MOAT_DUG_OR_PLANNED)) != 0) { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::clearMoatDataAtTile, this)(tile + - DAT_ViewportRenderState::instance + .translationMatrix[DAT_ViewportRenderState::instance + .tileTranslationMatrix_YComponent[tile]] + .addXgetTile, + DAT_ViewportRenderState::instance.tileTranslationMatrix_YComponent[tile]); + this->LogicLayer[tile] = this->LogicLayer[tile] & ~(L_MOAT | L_MOAT_DUG_OR_PLANNED); + } + this->LogicLayer[tile] = this->LogicLayer[tile] + & (L_STOCKPILEUnk | L_PLAIN1_AND_FARM | L_BORDER | L_BORDER_EDGE | L_BUILDING + | L_MOAT_DUG_OR_PLANNED | L_DEFAULT_EARTH_OR_TEXTURE | L_UNKNOWN_WALL_RELATED | L_CLIMBABLE + | L_FARM_FIELD_WHEAT | L_FARM_FIELD_HOP | L_FARM_FIELD_APPLE | L_FARM_FIELD_DAIRY + | L_KEEP_NON_MANOR_HOUSE | L_MOAT); + this->MiscDisplayLayer[tile] = this->MiscDisplayLayer[tile] & 0xf83f; + this->Logic2Layer[tile] = 0; + if (this->HeightLayer[tile] == 80) { + this->Logic2Layer[tile] = L2_PLATEAU_MEDIUM; + } else if (this->HeightLayer[tile] == 130) { + this->Logic2Layer[tile] = L2_PLATEAU_HIGH; + } + this->WallOwnerLayer[tile] = 0; + MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::PathFindingState_Func::updatePathLinkagesInAllEightDirections, + DAT_PathFindingState::ptr)(y, tile); + } + index++; + } while (index < brushSize); + } + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/setMapSize.cpp b/src/OpenSHC/Map/TileMapState/setMapSize.cpp new file mode 100644 index 0000000000..c0c4b15a4b --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/setMapSize.cpp @@ -0,0 +1,22 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" + +namespace OpenSHC { +namespace Map { + + // FUNCTION: STRONGHOLDCRUSADER 0x004F6F90 + void TileMapState::setMapSize(int size) + { + int index = 0; + for (; size <= DAT_TerrainDefinedData::instance.MapSizes[index]; index++) {} + + if (DAT_TerrainDefinedData::instance.MapSizes[index] == -1) { + this->mapSize = DAT_TerrainDefinedData::instance.MapSizes[0]; + return; + } + this->mapSize = DAT_TerrainDefinedData::instance.MapSizes[index]; + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/setMiscDisplayLayer.cpp b/src/OpenSHC/Map/TileMapState/setMiscDisplayLayer.cpp new file mode 100644 index 0000000000..099d7560e7 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/setMiscDisplayLayer.cpp @@ -0,0 +1,126 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Map/Buildings/BuildingType.hpp" + +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::Buildings::BuildingType; + + // FUNCTION: STRONGHOLDCRUSADER 0x004FB0C0 + void TileMapState::setMiscDisplayLayer(int buildingID) + { + int rotation = this->mapOrientation / 2; + if (DAT_BuildingsState::instance.buildings[buildingID].unknownStockpileOrSignpostRelated == 0) { + return; + } + + int x = (short)DAT_BuildingsState::instance.buildings[buildingID].x; + int y = (short)DAT_BuildingsState::instance.buildings[buildingID].y; + uint size = DAT_BuildingsState::instance.buildings[buildingID].widthOrHeight; + OpenSHC::Map::Buildings::BuildingTypeShort type + = DAT_BuildingsState::instance.buildings[buildingID].buildingType; + int typeInt = (short)type; + int offsetIndex = rotation + size * 4; + int workerTile = DAT_TerrainDefinedData::instance.orientationRelativeBuildingTileOffset1[offsetIndex]; + int displayTile = DAT_TerrainDefinedData::instance.orientationRelativeBuildingTileOffset2[offsetIndex]; + int extraTile = -1; + switch (typeInt) { + case OpenSHC::Map::Buildings::BT_IRONMINE: + case OpenSHC::Map::Buildings::BT_PITCHRIG: + case OpenSHC::Map::Buildings::BT_HUNTERSHUT: + case OpenSHC::Map::Buildings::BT_BLACKSMITH: + case OpenSHC::Map::Buildings::BT_BREWERY: + case OpenSHC::Map::Buildings::BT_OILSMELTER: + case OpenSHC::Map::Buildings::BT_STABLES: + case OpenSHC::Map::Buildings::BT_MANORHOUSE: + case OpenSHC::Map::Buildings::BT_KEEPFOUR: + case OpenSHC::Map::Buildings::BT_KEEPFIVE: + case OpenSHC::Map::Buildings::BT_TUNNEL: + case OpenSHC::Map::Buildings::BT_FIREBALLISTA: + case OpenSHC::Map::Buildings::BT_MAYPOLE: + case OpenSHC::Map::Buildings::BT_CATAPULT: + case OpenSHC::Map::Buildings::BT_TREBUCHET: + case OpenSHC::Map::Buildings::BT_BATTERINGRAM: + case OpenSHC::Map::Buildings::BT_SIEGETOWER: + case OpenSHC::Map::Buildings::BT_SHIELD: + case OpenSHC::Map::Buildings::BT_UNKNOWN4: + /* these carry the worker on the display tile and the display on the worker tile */ + workerTile = displayTile; + displayTile = DAT_TerrainDefinedData::instance.orientationRelativeBuildingTileOffset1[offsetIndex]; + break; + case OpenSHC::Map::Buildings::BT_DRAWBRIDGE: + switch (rotation) { + case 0: + displayTile = 0x13; + extraTile = 6; + break; + case 1: + displayTile = 0x15; + extraTile = 8; + break; + case 2: + displayTile = 5; + extraTile = 0x12; + break; + case 3: + displayTile = 3; + extraTile = 0x10; + } + break; + case OpenSHC::Map::Buildings::BT_GALLOWS: + case OpenSHC::Map::Buildings::BT_GIBBET: + workerTile = -1; + } + + if ((int)size < 3 && type != OpenSHC::Map::Buildings::BT_GIBBET + && type != OpenSHC::Map::Buildings::BT_GALLOWS) { + this->MiscDisplayLayer[DAT_ViewportRenderState::instance.translationMatrix[y].addXgetTile + x] + = this->MiscDisplayLayer[DAT_ViewportRenderState::instance.translationMatrix[y].addXgetTile + x] | 4; + return; + } + + int index = 0; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)(index, size); + index++; + this->MiscDisplayLayer[DAT_ViewportRenderState::instance.translationMatrix[this->buildingY + y].addXgetTile + + x + this->buildingX] + = this->MiscDisplayLayer[DAT_ViewportRenderState::instance.translationMatrix[this->buildingY + y] + .addXgetTile + + x + this->buildingX] + & 0xfff3; + } while (index < this->constructionTileCount); + + index = 0; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)(index, size); + int tile = DAT_ViewportRenderState::instance.translationMatrix[this->buildingY + y].addXgetTile + x + + this->buildingX; + if (typeInt == OpenSHC::Map::Buildings::BT_GRANARY) { + this->MiscDisplayLayer[tile] = this->MiscDisplayLayer[tile] | 8; + } else if (typeInt == OpenSHC::Map::Buildings::BT_ARMORY) { + this->MiscDisplayLayer[tile] = this->MiscDisplayLayer[tile] | 8; + } else if (index == workerTile) { + this->MiscDisplayLayer[tile] = this->MiscDisplayLayer[tile] | 8; + /* fixme: xPosition and the field after it are written as one int */ + *(int*)&DAT_BuildingsState::instance.buildings[buildingID].xPosition = tile; + } + if (index == displayTile) { + this->MiscDisplayLayer[tile] = this->MiscDisplayLayer[tile] | 4; + DAT_BuildingsState::instance.buildings[buildingID].miscDisplayLayerTile = tile; + } + if (index == extraTile) { + this->MiscDisplayLayer[tile] = this->MiscDisplayLayer[tile] | 0xc; + DAT_BuildingsState::instance.buildings[buildingID].miscDisplayLayerTile = tile; + } + index++; + } while (index < this->constructionTileCount); + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/setSignpostDistanceForCampaignMission.cpp b/src/OpenSHC/Map/TileMapState/setSignpostDistanceForCampaignMission.cpp new file mode 100644 index 0000000000..6695af2132 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/setSignpostDistanceForCampaignMission.cpp @@ -0,0 +1,41 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Game/GameMode2.hpp" + +#include "OpenSHC/Globals/DAT_GameCore.hpp" +#include "OpenSHC/Globals/DAT_GameState.hpp" +#include "OpenSHC/Globals/DAT_MapPropertiesState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Game::GameMode2; + + // FUNCTION: STRONGHOLDCRUSADER 0x00500BB0 + void TileMapState::setSignpostDistanceForCampaignMission() + { + DAT_GameState::instance.mapAndTime.unk_signpostDistance = 30; + if (DAT_GameCore::instance.gameMode_2 == OpenSHC::Game::GM_CAMPAIGN_MISSION) { + if (DAT_GameCore::instance.missionNumber1to20 <= 2) { + DAT_GameState::instance.mapAndTime.unk_signpostDistance = 0; + return; + } + if (DAT_GameCore::instance.missionNumber1to20 <= 4) { + DAT_GameState::instance.mapAndTime.unk_signpostDistance = 15; + return; + } + if (DAT_GameCore::instance.missionNumber1to20 == 6) { + DAT_GameState::instance.mapAndTime.unk_signpostDistance = 37; + } + return; + } + + if (DAT_GameCore::instance.gameMode_2 == OpenSHC::Game::GM_ECONOMIC_CAMPAIGN_SH1 + || (DAT_GameCore::instance.gameMode_2 == OpenSHC::Game::GM_BUILDERUnk + && (int)DAT_MapPropertiesState::instance.SEC_U3_MapType2_1 >= 2)) { + DAT_GameState::instance.mapAndTime.unk_signpostDistance = 7; + } + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/setTerrain.cpp b/src/OpenSHC/Map/TileMapState/setTerrain.cpp new file mode 100644 index 0000000000..5deecb7c04 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/setTerrain.cpp @@ -0,0 +1,442 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" +#include "OpenSHC/Rendering/ViewportRenderState.func.hpp" +#include "OpenSHC/Game/GameMode2.hpp" +#include "OpenSHC/Map/TileMapState/NeighbourFlagsAsm.hpp" + +#include "OpenSHC/Globals/DAT_GameCore.hpp" +#include "OpenSHC/Globals/DAT_GameSynchronyState.hpp" +#include "OpenSHC/Globals/DAT_PathFindingState.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +// mask for the handwritten neighbour-flag macro; MASM has no "|", so this must be a literal +#define NEIGHBOUR_FLAGS_MASK_L2_BEACH 0x20 // L2_BEACH + +#pragma optimize("", off) + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Game::GameMode2; + using OpenSHC::Map::LogicHelpers::L2_BEACH; + using OpenSHC::Map::LogicHelpers::L2_EARTH_AND_STONES; + using OpenSHC::Map::LogicHelpers::L2_MOAT_UNDUG; + using OpenSHC::Map::LogicHelpers::L2_NONE; + using OpenSHC::Map::LogicHelpers::L2_OASIS_GRASS; + using OpenSHC::Map::LogicHelpers::L2_SCRUB; + using OpenSHC::Map::LogicHelpers::L2_STONES_OR_DRIVEN_SANDUnk; + using OpenSHC::Map::LogicHelpers::L2_THICK_SCRUB; + using OpenSHC::Map::LogicHelpers::L_BORDER; + using OpenSHC::Map::LogicHelpers::L_BOULDERS; + using OpenSHC::Map::LogicHelpers::L_BUILDING; + using OpenSHC::Map::LogicHelpers::L_FORD; + using OpenSHC::Map::LogicHelpers::L_IRON; + using OpenSHC::Map::LogicHelpers::L_KEEP_NON_MANOR_HOUSE; + using OpenSHC::Map::LogicHelpers::L_MARSH; + using OpenSHC::Map::LogicHelpers::L_MOAT; + using OpenSHC::Map::LogicHelpers::L_MOAT_DUG_OR_PLANNED; + using OpenSHC::Map::LogicHelpers::L_NONE; + using OpenSHC::Map::LogicHelpers::L_OIL; + using OpenSHC::Map::LogicHelpers::L_PEBBLES; + using OpenSHC::Map::LogicHelpers::L_PLAIN1_AND_FARM; + using OpenSHC::Map::LogicHelpers::L_PLAIN2_AND_PITCH; + using OpenSHC::Map::LogicHelpers::L_RIVER; + using OpenSHC::Map::LogicHelpers::L_ROCKY; + using OpenSHC::Map::LogicHelpers::L_SEA; + using OpenSHC::Map::LogicHelpers::L_UNNAMED_0x40; + using OpenSHC::Map::LogicHelpers::L_WALL_OR_GATEHOUSE; + + // FUNCTION: STRONGHOLDCRUSADER 0x00512940 + void TileMapState::setTerrain(int playerID, int tile, uint yParam, uint brushType, Logic1 flags1, Logic2 flags2) + { + /* + Holds one expansion of the handwritten neighbour-flag macro (see NeighbourFlagsAsm.hpp), + so the original was built without optimisation and the pragma above is needed to reproduce + its frame-pointer, reload-per-access shape. The locals are declared together because at + /Od the stack slots are observable and MSVC assigns them per function, not per scope. + + L_UNNAMED_0x40 is the one Logic1 bit the generated enum has no name for; the original both + tests flags1 against it and sets it on the tile. + */ + int baseTile; + uint baseY; + uint x; + int moatEnemyRange; + int moatOpponentRange; + int index; + int size; + + size = DAT_TerrainDefinedData::instance.BrushSizeArray[brushType]; + baseTile = tile; + baseY = yParam; + if (DAT_GameSynchronyState::instance.currentGameMode != OpenSHC::Game::GM_SOLITARY) { + moatEnemyRange = 0xf; + moatOpponentRange = 7; + } else { + moatEnemyRange = 0x1e; + moatOpponentRange = 0x1e; + } + + if (DAT_GameCore::instance.gameMode_2 == OpenSHC::Game::GM_EDITOR && flags1 != L_MOAT + && (flags2 == L2_EARTH_AND_STONES || flags2 == L2_OASIS_GRASS || flags2 == L2_BEACH + || flags2 == L2_STONES_OR_DRIVEN_SANDUnk || flags2 == L2_SCRUB || flags2 == L2_THICK_SCRUB)) { + /* + this functions processes all oasis tiles + */ + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::setLand, this)(tile, yParam, brushType); + } + if (flags1 == L_MOAT) { + size = 9; + } + + for (index = 0; index < size; index++) { + if (flags1 == L_MOAT) { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getTileForBrush, this)( + 0, index, &tile, (int*)&yParam, baseTile, baseY); + } else { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getTileForBrush, this)( + 1, index, &tile, (int*)&yParam, baseTile, baseY); + } + if ((this->LogicLayer[tile] & L_BORDER) != 0) { + continue; + } + + if (flags1 == L_SEA) { + if ((this->LogicLayer[tile] & (L_BUILDING | L_KEEP_NON_MANOR_HOUSE)) != 0 + || this->BuildingLayer[tile] != 0 || (this->LogicLayer[tile] & L_WALL_OR_GATEHOUSE) != 0 + || this->OrganismLayer[tile] != 0) { + continue; + } + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_UNNAMED_0x40; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_RIVER; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_FORD; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_ROCKY; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_BOULDERS; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_PEBBLES; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_IRON; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_MARSH; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_OIL; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_MOAT; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_PLAIN2_AND_PITCH; + this->Logic2Layer[tile] = 0; + this->LogicLayer[tile] = this->LogicLayer[tile] | L_SEA; + this->HeightLayer[tile] = 0; + this->DefaultHeightLayer[tile] = 0; + this->forceUpdateLogicalAndMiscDisplayLayers = 1; + } else if (flags1 == L_RIVER || flags1 == L_FORD) { + if ((this->LogicLayer[tile] & (L_BUILDING | L_KEEP_NON_MANOR_HOUSE)) != 0 + || this->BuildingLayer[tile] != 0 || (this->LogicLayer[tile] & L_WALL_OR_GATEHOUSE) != 0 + || this->OrganismLayer[tile] != 0) { + continue; + } + if (flags2 != L2_NONE && (this->LogicLayer[tile] & L_RIVER) == 0) { + continue; + } + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_UNNAMED_0x40; + if (flags1 == L_RIVER) { + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_FORD; + } else { + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_RIVER; + } + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_ROCKY; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_BOULDERS; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_PEBBLES; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_IRON; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_MARSH; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_OIL; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_MOAT; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_SEA; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_PLAIN2_AND_PITCH; + this->Logic2Layer[tile] = 0; + if (flags2 != L2_BEACH) { + this->WallGFXLayer[tile] = this->RandomLayer[tile] & 7; + } + if (flags2 == L2_OASIS_GRASS) { + this->Logic2Layer[tile] = L2_OASIS_GRASS; + } + if (flags2 == L2_BEACH) { + this->Logic2Layer[tile] = L2_BEACH; + this->WallGFXLayer[tile] = ((ushort)DAT_GameCore::instance.mapTimeInTicks & 8) + + this->WallGFXLayer[tile] * 0x20 + (this->RandomLayer[tile] & 7) * 0x400; + } + this->LogicLayer[tile] = this->LogicLayer[tile] | flags1; + if (this->HeightLayer[tile] > 7) { + this->HeightLayer[tile] = this->DefaultHeightLayer[tile] - 8; + this->forceUpdateLogicalAndMiscDisplayLayers = 1; + } + } else if (flags1 == L_ROCKY) { + if ((this->LogicLayer[tile] & (L_BUILDING | L_KEEP_NON_MANOR_HOUSE)) != 0 + || this->BuildingLayer[tile] != 0 || (this->LogicLayer[tile] & L_WALL_OR_GATEHOUSE) != 0 + || (this->LogicLayer[tile] & L_RIVER) != 0 || this->OrganismLayer[tile] != 0) { + continue; + } + if ((this->LogicLayer[tile] & L_SEA) == 0) { + if (this->HeightLayer[tile] < 8) { + this->HeightLayer[tile] = 8; + this->DefaultHeightLayer[tile] = 8; + } + } else { + this->HeightLayer[tile] = 0; + this->DefaultHeightLayer[tile] = 0; + } + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_SEA; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_RIVER; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_FORD; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_UNNAMED_0x40; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_BOULDERS; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_PEBBLES; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_IRON; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_MARSH; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_OIL; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_MOAT; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_PLAIN2_AND_PITCH; + this->Logic2Layer[tile] = 0; + this->LogicLayer[tile] = this->LogicLayer[tile] | L_ROCKY; + } else if (flags1 == L_IRON) { + if ((this->LogicLayer[tile] & (L_BUILDING | L_KEEP_NON_MANOR_HOUSE)) != 0 + || this->BuildingLayer[tile] != 0 || (this->LogicLayer[tile] & L_WALL_OR_GATEHOUSE) != 0 + || (this->LogicLayer[tile] & L_SEA) != 0 || (this->LogicLayer[tile] & L_RIVER) != 0 + || this->OrganismLayer[tile] != 0) { + continue; + } + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_RIVER; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_FORD; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_ROCKY; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_PEBBLES; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_BOULDERS; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_MARSH; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_OIL; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_MOAT; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_PLAIN2_AND_PITCH; + this->Logic2Layer[tile] = 0; + this->LogicLayer[tile] = this->LogicLayer[tile] | L_IRON; + } else if (flags1 == L_PEBBLES) { + if ((this->LogicLayer[tile] & (L_BUILDING | L_KEEP_NON_MANOR_HOUSE)) != 0 + || this->BuildingLayer[tile] != 0 || (this->LogicLayer[tile] & L_WALL_OR_GATEHOUSE) != 0 + || (this->LogicLayer[tile] & L_RIVER) != 0 || this->OrganismLayer[tile] != 0) { + continue; + } + if ((this->LogicLayer[tile] & L_SEA) == 0) { + if (this->HeightLayer[tile] < 8) { + this->HeightLayer[tile] = 8; + this->DefaultHeightLayer[tile] = 8; + } + } else { + this->HeightLayer[tile] = 0; + this->DefaultHeightLayer[tile] = 0; + } + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_SEA; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_UNNAMED_0x40; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_RIVER; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_FORD; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_ROCKY; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_BOULDERS; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_IRON; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_MARSH; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_OIL; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_MOAT; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_PLAIN2_AND_PITCH; + this->Logic2Layer[tile] = 0; + this->LogicLayer[tile] = this->LogicLayer[tile] | L_PEBBLES; + } else if (flags1 == L_MARSH) { + if ((this->LogicLayer[tile] & (L_BUILDING | L_KEEP_NON_MANOR_HOUSE)) != 0 + || this->BuildingLayer[tile] != 0 || (this->LogicLayer[tile] & L_WALL_OR_GATEHOUSE) != 0 + || (this->LogicLayer[tile] & L_RIVER) != 0 || this->OrganismLayer[tile] != 0) { + continue; + } + this->HeightLayer[tile] = 8; + this->DefaultHeightLayer[tile] = 8; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_SEA; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_UNNAMED_0x40; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_RIVER; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_FORD; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_ROCKY; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_BOULDERS; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_IRON; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_OIL; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_MOAT; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_PLAIN2_AND_PITCH; + this->Logic2Layer[tile] = 0; + this->LogicLayer[tile] = this->LogicLayer[tile] | L_MARSH; + } else if (flags1 == L_OIL) { + if ((this->LogicLayer[tile] & (L_BUILDING | L_KEEP_NON_MANOR_HOUSE)) != 0 + || this->BuildingLayer[tile] != 0 || (this->LogicLayer[tile] & L_WALL_OR_GATEHOUSE) != 0 + || (this->LogicLayer[tile] & L_RIVER) != 0 || this->OrganismLayer[tile] != 0) { + continue; + } + if ((this->LogicLayer[tile] & L_MARSH) == 0) { + continue; + } + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_SEA; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_UNNAMED_0x40; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_RIVER; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_FORD; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_ROCKY; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_BOULDERS; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_IRON; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_PLAIN2_AND_PITCH; + this->Logic2Layer[tile] = 0; + this->LogicLayer[tile] = this->LogicLayer[tile] | L_OIL; + } else if (flags1 == L_MOAT) { + if (this->OrganismLayer[tile] != 0 + || (this->LogicLayer[tile] & (L_BUILDING | L_KEEP_NON_MANOR_HOUSE)) != 0 + || this->BuildingLayer[tile] != 0 || (this->LogicLayer[tile] & L_WALL_OR_GATEHOUSE) != 0 + || (this->LogicLayer[tile] & L_SEA) != 0 || (this->LogicLayer[tile] & L_RIVER) != 0 + || (this->LogicLayer[tile] & L_FORD) != 0 || (this->LogicLayer[tile] & L_ROCKY) != 0 + || (this->LogicLayer[tile] & L_BOULDERS) != 0 || (this->LogicLayer[tile] & L_IRON) != 0 + || (this->LogicLayer[tile] & L_MARSH) != 0 || (this->LogicLayer[tile] & L_PLAIN1_AND_FARM) != 0) { + continue; + } + x = MACRO_CALL_MEMBER(OpenSHC::Rendering::ViewportRenderState_Func::computeTileXOffset, + DAT_ViewportRenderState::ptr)(tile, yParam); + if (DAT_GameCore::instance.gameMode_2 != OpenSHC::Game::GM_EDITOR + && DAT_GameCore::instance.gameMode_2 != OpenSHC::Game::GM_SIEGE_THAT + && MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::isEnemyTooCloseUnk, + DAT_PathFindingState::ptr)(playerID, x, yParam, moatEnemyRange) + != FALSE) { + continue; + } + if (DAT_GameSynchronyState::instance.currentGameMode != OpenSHC::Game::GM_SOLITARY) { + if (MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::isOpponentBuildingInRange, + DAT_PathFindingState::ptr)(playerID, x, yParam, moatOpponentRange, -1, -1, + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getCastleBuildRangeForMapSize, this)() + + 5) + != 0) { + continue; + } + } + if ((this->LogicLayer[tile] & L_MOAT) != 0 && flags2 != L2_MOAT_UNDUG) { + continue; + } + if (this->HeightLayer[tile] >= 0xd) { + continue; + } + if (flags2 == L2_NONE) { + if ((this->LogicLayer[tile] & L_MOAT_DUG_OR_PLANNED) == 0 + && MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::createMoatData, this)( + playerID, x, yParam, 0) + != 0) { + this->LogicLayer[tile] = this->LogicLayer[tile] | L_MOAT_DUG_OR_PLANNED; + } + } else if (flags2 == L2_SCRUB) { + if ((this->LogicLayer[tile] & L_MOAT_DUG_OR_PLANNED) != 0) { + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_MOAT_DUG_OR_PLANNED; + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::clearMoatDataAtTile, this)(x, yParam); + } + } else { + this->HeightLayer[tile] = 8; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_PLAIN2_AND_PITCH; + this->Logic2Layer[tile] = 0; + if (flags2 == L2_EARTH_AND_STONES) { + if (MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::createMoatData, this)( + playerID, x, yParam, 1) + != 0) { + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_MOAT_DUG_OR_PLANNED; + this->LogicLayer[tile] = this->LogicLayer[tile] | L_MOAT; + this->HeightLayer[tile] = 0; + } + } else if (flags2 == L2_MOAT_UNDUG) { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::clearMoatDataAtTile, this)(x, yParam); + this->HeightLayer[tile] = 8; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_MOAT_DUG_OR_PLANNED; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_MOAT; + } + } + } else if (flags2 != L2_EARTH_AND_STONES && flags2 != L2_OASIS_GRASS && flags2 != L2_BEACH + && flags2 != L2_STONES_OR_DRIVEN_SANDUnk && flags2 != L2_SCRUB && flags2 != L2_THICK_SCRUB) { + if (flags1 == L_BOULDERS) { + if ((this->LogicLayer[tile] & (L_BUILDING | L_KEEP_NON_MANOR_HOUSE)) != 0 + || this->BuildingLayer[tile] != 0 || (this->LogicLayer[tile] & L_WALL_OR_GATEHOUSE) != 0 + || (this->LogicLayer[tile] & L_RIVER) != 0 || this->OrganismLayer[tile] != 0) { + continue; + } + if ((this->LogicLayer[tile] & L_SEA) == 0) { + if (this->HeightLayer[tile] < 8) { + this->HeightLayer[tile] = 8; + this->DefaultHeightLayer[tile] = 8; + } + } else { + this->HeightLayer[tile] = 0; + this->DefaultHeightLayer[tile] = 0; + } + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_SEA; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_UNNAMED_0x40; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_RIVER; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_FORD; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_ROCKY; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_PEBBLES; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_IRON; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_MARSH; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_OIL; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_MOAT; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_PLAIN2_AND_PITCH; + this->Logic2Layer[tile] = 0; + this->LogicLayer[tile] = this->LogicLayer[tile] | L_BOULDERS; + } else if (flags1 == L_UNNAMED_0x40) { + if ((this->LogicLayer[tile] & L_SEA) == 0 + || (this->LogicLayer[tile] & (L_BUILDING | L_KEEP_NON_MANOR_HOUSE)) != 0 + || this->BuildingLayer[tile] != 0 || (this->LogicLayer[tile] & L_WALL_OR_GATEHOUSE) != 0 + || this->OrganismLayer[tile] != 0) { + continue; + } + this->LogicLayer[tile] = this->LogicLayer[tile] | L_UNNAMED_0x40; + } + } else { + if ((this->LogicLayer[tile] & (L_BUILDING | L_KEEP_NON_MANOR_HOUSE)) != 0 + || this->BuildingLayer[tile] != 0 || (this->LogicLayer[tile] & L_WALL_OR_GATEHOUSE) != 0 + || (this->LogicLayer[tile] & (L_SEA | L_RIVER | L_FORD | L_MARSH | L_MOAT)) != 0 + || this->OrganismLayer[tile] != 0) { + continue; + } + if (flags2 == L2_EARTH_AND_STONES) { + if ((this->LogicLayer[tile] & L_IRON) != 0 || (this->LogicLayer[tile] & L_BOULDERS) != 0 + || (this->Logic2Layer[tile] & L2_BEACH) != 0) { + continue; + } + MACRO_NEIGHBOUR_FLAGS_TERRAIN_8(1, NEIGHBOUR_FLAGS_MASK_L2_BEACH) + if (this->bitFlag != 0) { + continue; + } + } + + this->MiscDisplayLayer[tile] = this->MiscDisplayLayer[tile] & 0xffdf; + if (flags2 != L2_STONES_OR_DRIVEN_SANDUnk && flags2 != L2_SCRUB && flags2 != L2_THICK_SCRUB + && flags2 != L2_EARTH_AND_STONES && flags2 != L2_OASIS_GRASS) { + if (flags2 == L2_BEACH) { + this->HeightLayer[tile] = 0; + this->DefaultHeightLayer[tile] = 0; + } else { + this->HeightLayer[tile] = 8; + this->DefaultHeightLayer[tile] = 8; + } + } + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_SEA; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_UNNAMED_0x40; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_RIVER; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_FORD; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_ROCKY; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_BOULDERS; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_IRON; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_MARSH; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_OIL; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_MOAT; + if (flags2 != L2_EARTH_AND_STONES) { + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_PLAIN2_AND_PITCH; + } + this->Logic2Layer[tile] = (byte)flags2; + } + + if (flags1 != L_NONE) { + MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::PathFindingState_Func::updatePathLinkagesInAllEightDirections, + DAT_PathFindingState::ptr)(yParam, tile); + } + } + } + +} +} + +#pragma optimize("", on) diff --git a/src/OpenSHC/Map/TileMapState/setXYBasedOnMoatID.cpp b/src/OpenSHC/Map/TileMapState/setXYBasedOnMoatID.cpp new file mode 100644 index 0000000000..f5e7c4fdcd --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/setXYBasedOnMoatID.cpp @@ -0,0 +1,51 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + + // FUNCTION: STRONGHOLDCRUSADER 0x005003D0 + int TileMapState::setXYBasedOnMoatID(int moatID, int param_2, uint x, uint y) + { + if (x > 399 || y > 399) { + return 0; + } + if (DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[y * 400 + x] == 0) { + return 0; + } + + int tile = DAT_ViewportRenderState::instance.translationMatrix[y].addXgetTile + x; + if (param_2 == 1) { + this->ALG_MoatXResult = this->moats[moatID].x; + this->ALG_MoatYResult = this->moats[moatID].y; + return DAT_ViewportRenderState::instance.translationMatrix[this->ALG_MoatYResult].addXgetTile + + this->ALG_MoatXResult; + } + if (param_2 != 2) { + return 0; + } + + for (int direction = 0; direction < 8; direction++) { + int neighbour + = this->directionTranslationMatrix[this->moats[moatID].y][direction] + this->moats[moatID].tile; + if ((uint)(this->HeightLayer[tile] + 0x10) < (uint)this->HeightLayer[neighbour]) { + continue; + } + if (this->PathConnectionLayer[neighbour] != this->PathConnectionLayer[tile]) { + continue; + } + + this->someMoatTile = this->moats[moatID].tile; + this->ALG_MoatXResult = this->moats[moatID].x + + DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[direction].int_.xOffset; + this->ALG_MoatYResult = this->moats[moatID].y + + DAT_TerrainDefinedData::instance.clockwiseCardinalTranslationMatrix[direction].int_.yOffset; + return neighbour; + } + return 0; + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/setupAllMapSections.cpp b/src/OpenSHC/Map/TileMapState/setupAllMapSections.cpp new file mode 100644 index 0000000000..88efcd1abc --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/setupAllMapSections.cpp @@ -0,0 +1,172 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Game/GameStateStructures.func.hpp" +#include "OpenSHC/Global.func.hpp" +#include "OpenSHC/IO/LowLevelMemory.func.hpp" +#include "OpenSHC/Map.func.hpp" +#include "OpenSHC/Map/Buildings/BuildingsState.func.hpp" +#include "OpenSHC/Map/Entities/EntityState.func.hpp" +#include "OpenSHC/Map/LandscapeState.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/Rendering/ViewportRenderState.func.hpp" +#include "OpenSHC/UI/MinimapViewState.func.hpp" +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +#include "OpenSHC/Globals/DAT_AICState.hpp" +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_EntityState.hpp" +#include "OpenSHC/Globals/DAT_GameCore.hpp" +#include "OpenSHC/Globals/DAT_GameState.hpp" +#include "OpenSHC/Globals/DAT_LandscapeState.hpp" +#include "OpenSHC/Globals/DAT_LowLevelMemory.hpp" +#include "OpenSHC/Globals/DAT_MinimapViewState.hpp" +#include "OpenSHC/Globals/DAT_PathFindingState.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_TribesState.hpp" +#include "OpenSHC/Globals/DAT_UnitsState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" +#include "OpenSHC/Globals/DAT_WallAndPitchState.hpp" +#include "OpenSHC/Globals/DAT_WindowAndDirectDraw.hpp" +#include "OpenSHC/Globals/GMTotalPicturesProcessed.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_BORDER; + using OpenSHC::Map::LogicHelpers::L_BORDER_EDGE; + + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x00512100 + void TileMapState::setupAllMapSections() + { + this->temporaryTerrainTypeIndex = 0; + this->SEC_Section1052 = 0; + this->SEC_Section1053 = 0; + this->SEC_Section1054 = 0; + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::setupTileMapSections, this)(); + DAT_WallAndPitchState::instance.countdown = 0; + MACRO_CALL_MEMBER(OpenSHC::Rendering::ViewportRenderState_Func::setTileSystemMemoryLookupArrays, + DAT_ViewportRenderState::ptr)(); + MACRO_CALL_MEMBER(OpenSHC::Rendering::ViewportRenderState_Func::tweakValidTilesToExcludeMapBorders, + DAT_ViewportRenderState::ptr)(); + MACRO_CALL_MEMBER(OpenSHC::Rendering::ViewportRenderState_Func::setupViewport, DAT_ViewportRenderState::ptr)( + 0, 0, DAT_WindowAndDirectDraw::instance.resolutionX, DAT_WindowAndDirectDraw::instance.resolutionY - 128); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::setupLogicalMapBorders, this)(); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::updateShowHiLayerOrResetChangedLayer, this)(); + + /* the border tiles get their own graphic, everything else the plain one */ + for (int tile = 0; tile < 80400; tile += 6) { + if (this->LogicLayer[tile + 0] == L_BORDER) { + this->GfxLayer[tile + 0] = (ushort)GMTotalPicturesProcessed::instance[2]; + } else if (this->LogicLayer[tile + 0] == L_BORDER_EDGE) { + this->GfxLayer[tile + 0] = (ushort)GMTotalPicturesProcessed::instance[2] + 1; + } else { + this->GfxLayer[tile + 0] = (ushort)GMTotalPicturesProcessed::instance[2] + 2; + } + if (this->LogicLayer[tile + 1] == L_BORDER) { + this->GfxLayer[tile + 1] = (ushort)GMTotalPicturesProcessed::instance[2]; + } else if (this->LogicLayer[tile + 1] == L_BORDER_EDGE) { + this->GfxLayer[tile + 1] = (ushort)GMTotalPicturesProcessed::instance[2] + 1; + } else { + this->GfxLayer[tile + 1] = (ushort)GMTotalPicturesProcessed::instance[2] + 2; + } + if (this->LogicLayer[tile + 2] == L_BORDER) { + this->GfxLayer[tile + 2] = (ushort)GMTotalPicturesProcessed::instance[2]; + } else if (this->LogicLayer[tile + 2] == L_BORDER_EDGE) { + this->GfxLayer[tile + 2] = (ushort)GMTotalPicturesProcessed::instance[2] + 1; + } else { + this->GfxLayer[tile + 2] = (ushort)GMTotalPicturesProcessed::instance[2] + 2; + } + if (this->LogicLayer[tile + 3] == L_BORDER) { + this->GfxLayer[tile + 3] = (ushort)GMTotalPicturesProcessed::instance[2]; + } else if (this->LogicLayer[tile + 3] == L_BORDER_EDGE) { + this->GfxLayer[tile + 3] = (ushort)GMTotalPicturesProcessed::instance[2] + 1; + } else { + this->GfxLayer[tile + 3] = (ushort)GMTotalPicturesProcessed::instance[2] + 2; + } + if (this->LogicLayer[tile + 4] == L_BORDER) { + this->GfxLayer[tile + 4] = (ushort)GMTotalPicturesProcessed::instance[2]; + } else if (this->LogicLayer[tile + 4] == L_BORDER_EDGE) { + this->GfxLayer[tile + 4] = (ushort)GMTotalPicturesProcessed::instance[2] + 1; + } else { + this->GfxLayer[tile + 4] = (ushort)GMTotalPicturesProcessed::instance[2] + 2; + } + if (this->LogicLayer[tile + 5] == L_BORDER) { + this->GfxLayer[tile + 5] = (ushort)GMTotalPicturesProcessed::instance[2]; + } else if (this->LogicLayer[tile + 5] == L_BORDER_EDGE) { + this->GfxLayer[tile + 5] = (ushort)GMTotalPicturesProcessed::instance[2] + 1; + } else { + this->GfxLayer[tile + 5] = (ushort)GMTotalPicturesProcessed::instance[2] + 2; + } + } + + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ShortValue, DAT_LowLevelMemory::ptr)( + 80400, 1, this->PillarGFXLayer); + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 80400, '\b', this->HeightLayer); + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 80400, '\b', this->DefaultHeightLayer); + DAT_PathFindingState::instance.searchGeneration = 1; + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 160800, '\0', DAT_TileMapState::instance.WalkLayer); + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::setChangedLayerZeroBasedOn40x40Layer, + DAT_PathFindingState::ptr)(0); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::updateLogicalTileMapRelatedSections, this)(); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::updateGfxLayer, this)(); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::updateGFXLayers, this)(); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::resetMoatArray, this)(); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::resetPitchDitchArray, this)(); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::toggleFlatView, this)(0); + DAT_TileMapState::instance.field95_0x5548d0 = 0; + DAT_TileMapState::instance.flatViewToggleValue2 = 0; + MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::clearBuildings, DAT_BuildingsState::ptr)(); + MACRO_CALL_MEMBER(OpenSHC::Map::LandscapeState_Func::clearRocksAndTrees, DAT_LandscapeState::ptr)(); + MACRO_CALL_MEMBER(OpenSHC::Map::LandscapeState_Func::resetWind, DAT_LandscapeState::ptr)(); + MACRO_CALL(OpenSHC::Global_Func::DoNothing)(); + MACRO_CALL_MEMBER(OpenSHC::Map::Units::UnitsState_Func::clearAllUnits, DAT_UnitsState::ptr)(); + MACRO_CALL_MEMBER(OpenSHC::Map::Units::TribesState_Func::clearAllTribes, DAT_TribesState::ptr)(); + MACRO_CALL_MEMBER(OpenSHC::Game::GameStateStructures_Func::clearMapAndTimeAndPlayerData, DAT_GameState::ptr)(); + MACRO_CALL_MEMBER( + OpenSHC::Game::GameStateStructures_Func::resetVariousCountsAndStatisticsAndStartGoodsAndResources, + DAT_GameState::ptr)(); + MACRO_CALL_MEMBER( + OpenSHC::Game::GameStateStructures_Func::clearCurrentResourcesAndStrongWalls, DAT_GameState::ptr)(); + MACRO_CALL_MEMBER( + OpenSHC::Game::GameStateStructures_Func::initializeGameStateAfterMapLoad, DAT_GameState::ptr)(); + MACRO_CALL_MEMBER(OpenSHC::Game::GameStateStructures_Func::fillWith0xFF, DAT_GameState::ptr)(); + MACRO_CALL_MEMBER(OpenSHC::Map::Units::TribesState_Func::clearAnimalSpawnLocationsUnk, DAT_TribesState::ptr)(); + + for (int tribe = 0; tribe < 1000; tribe++) { + DAT_AICState::instance.tribeIDArray[tribe] = 0; + DAT_AICState::instance.tribeUIDArray[tribe] = 0; + } + MACRO_CALL(OpenSHC::Global_Func::DoNothing)(); + MACRO_CALL(OpenSHC::Global_Func::DoNothing)(); + MACRO_CALL_MEMBER( + OpenSHC::Map::Entities::EntityState_Func::clearEntityArrayAndSeagullArray, DAT_EntityState::ptr)(); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::setChangedLayerToThreeAndMapping0x40x40, this)(); + this->forceUpdateLogicalAndMiscDisplayLayers = 1; + this->forceUpdateTextureTilemap = 1; + this->forceUpdateGFXLayers = 1; + this->forceUpdateMacroLayerFlag = 1; + this->field68_0x55487c = 200; + MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::PathFindingState_Func::updatePathLinkageLayerForEachBuildingAtEachTile, + DAT_PathFindingState::ptr)(); + MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::PathFindingState_Func::updateSeparateAreaTileMap, DAT_PathFindingState::ptr)(1); + this->forceUpdateMacroLayerFlag = 1; + this->field68_0x55487c = 500; + MACRO_CALL_MEMBER( + OpenSHC::UI::MinimapViewState_Func::setTileColorsDependingOnMapSize, DAT_MinimapViewState::ptr)(0, 100); + MACRO_CALL_MEMBER( + OpenSHC::UI::MinimapViewState_Func::setMapPropertyDependingOnMapSize, DAT_MinimapViewState::ptr)(0, 100); + DAT_GameCore::instance.currentlyInGameUnk_0xa4 = FALSE; + MACRO_CALL(OpenSHC::Map_Func::ResetSomeValuesFunctionUnk)(); + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/setupBuildingSizeIndexMapping.cpp b/src/OpenSHC/Map/TileMapState/setupBuildingSizeIndexMapping.cpp new file mode 100644 index 0000000000..6a5414abd3 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/setupBuildingSizeIndexMapping.cpp @@ -0,0 +1,26 @@ +#include "../TileMapState.func.hpp" + +namespace OpenSHC { +namespace Map { + + // FUNCTION: STRONGHOLDCRUSADER 0x00503720 + void TileMapState::setupBuildingSizeIndexMapping() + { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::setupBuildingSizeIndexMappingForBuildingWithSize, this)(0); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::setupBuildingSizeIndexMappingForBuildingWithSize, this)(1); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::setupBuildingSizeIndexMappingForBuildingWithSize, this)(2); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::setupBuildingSizeIndexMappingForBuildingWithSize, this)(3); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::setupBuildingSizeIndexMappingForBuildingWithSize, this)(4); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::setupBuildingSizeIndexMappingForBuildingWithSize, this)(5); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::setupBuildingSizeIndexMappingForBuildingWithSize, this)(6); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::setupBuildingSizeIndexMappingForBuildingWithSize, this)(7); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::setupBuildingSizeIndexMappingForBuildingWithSize, this)(8); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::setupBuildingSizeIndexMappingForBuildingWithSize, this)(9); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::setupBuildingSizeIndexMappingForBuildingWithSize, this)(10); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::setupBuildingSizeIndexMappingForBuildingWithSize, this)(11); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::setupBuildingSizeIndexMappingForBuildingWithSize, this)(12); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::setupBuildingSizeIndexMappingForBuildingWithSize, this)(13); + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/setupBuildingSizeIndexMappingForBuildingWithSize.cpp b/src/OpenSHC/Map/TileMapState/setupBuildingSizeIndexMappingForBuildingWithSize.cpp new file mode 100644 index 0000000000..f118ca8bdf --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/setupBuildingSizeIndexMappingForBuildingWithSize.cpp @@ -0,0 +1,129 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/IO/LowLevelMemory.func.hpp" + +#include "OpenSHC/Globals/DAT_BuildingSizeIndexMapping.hpp" +#include "OpenSHC/Globals/DAT_LowLevelMemory.hpp" + +namespace OpenSHC { +namespace Map { + + // FUNCTION: STRONGHOLDCRUSADER 0x004F9590 + void TileMapState::setupBuildingSizeIndexMappingForBuildingWithSize(int buildingSize) + { + int tileCount = buildingSize * buildingSize; + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + 4056, '\0', DAT_BuildingSizeIndexMapping::instance + buildingSize); + if (buildingSize <= 1) { + return; + } + + /* pass 0: the unrotated footprint, in reading order */ + for (int y = 0; y < buildingSize; y++) { + for (int x = 0; x < buildingSize; x++) { + DAT_BuildingSizeIndexMapping::instance[buildingSize][y * buildingSize + x][0] = x; + DAT_BuildingSizeIndexMapping::instance[buildingSize][y * buildingSize + x][1] = y; + } + } + + /* passes 1 to 4: the same tiles walked diagonally, one pass per rotation */ + int last = tileCount - 1; + int x = 0; + int y = 0; + int run = 1; + int index = last; + for (int diagonal = 0; diagonal < buildingSize * 2 - 1; diagonal++) { + for (int step = 0; step < run; step++) { + DAT_BuildingSizeIndexMapping::instance[buildingSize][y * buildingSize + x][2] = index; + index--; + if (step < run - 1) { + x--; + y++; + } + } + if (diagonal < buildingSize - 1) { + run++; + x = diagonal + 1; + y = 0; + } else { + run--; + x = buildingSize - 1; + y = (1 - (buildingSize - 1)) + diagonal; + } + } + + x = buildingSize - 1; + y = 0; + run = 1; + index = last; + for (int diagonal = 0; diagonal < buildingSize * 2 - 1; diagonal++) { + for (int step = 0; step < run; step++) { + DAT_BuildingSizeIndexMapping::instance[buildingSize][y * buildingSize + x][3] = index; + index--; + if (step < run - 1) { + x--; + y--; + } + } + if (diagonal < buildingSize - 1) { + run++; + x = buildingSize - 1; + y = diagonal + 1; + } else { + run--; + x = (buildingSize - 1) + (buildingSize - 2) - diagonal; + y = buildingSize - 1; + } + } + + x = buildingSize - 1; + y = buildingSize - 1; + run = 1; + index = last; + for (int diagonal = 0; diagonal < buildingSize * 2 - 1; diagonal++) { + for (int step = 0; step < run; step++) { + DAT_BuildingSizeIndexMapping::instance[buildingSize][y * buildingSize + x][4] = index; + index--; + if (step < run - 1) { + x++; + y--; + } + } + if (diagonal < buildingSize - 1) { + run++; + x = buildingSize - 2 - diagonal; + y = buildingSize - 1; + } else { + run--; + x = 0; + y = (buildingSize - 2 - diagonal) + (buildingSize - 1); + } + } + + x = 0; + y = buildingSize - 1; + run = 1; + index = last; + for (int diagonal = 0; diagonal < buildingSize * 2 - 1; diagonal++) { + for (int step = 0; step < run; step++) { + DAT_BuildingSizeIndexMapping::instance[buildingSize][y * buildingSize + x][5] = index; + index--; + if (step < run - 1) { + x++; + y++; + } + } + if (diagonal < buildingSize - 1) { + run++; + x = 0; + y = buildingSize - 2 - diagonal; + } else { + run--; + x = (1 - (buildingSize - 1)) + diagonal; + y = 0; + } + } + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/setupLogicalMapBorders.cpp b/src/OpenSHC/Map/TileMapState/setupLogicalMapBorders.cpp new file mode 100644 index 0000000000..f5dd47d0de --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/setupLogicalMapBorders.cpp @@ -0,0 +1,43 @@ +#include "../TileMapState.func.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_BORDER; + using OpenSHC::Map::LogicHelpers::L_BORDER_EDGE; + + // FUNCTION: STRONGHOLDCRUSADER 0x004F6C60 + void TileMapState::setupLogicalMapBorders() + { + int rowWidth = 0; + int index = 0; + for (; rowWidth < 400; rowWidth += 2) { + this->LogicLayer[index] = L_BORDER; + index++; + if (rowWidth > 0) { + this->LogicLayer[index] = L_BORDER_EDGE; + } + index = index + rowWidth; + if (rowWidth > 0) { + this->LogicLayer[index - 1] = L_BORDER_EDGE; + } + this->LogicLayer[index] = L_BORDER; + index++; + } + for (rowWidth = 398;rowWidth >= 0; rowWidth -= 2) { + this->LogicLayer[index] = L_BORDER; + index++; + if (rowWidth > 0) { + this->LogicLayer[index] = L_BORDER_EDGE; + } + index = index + rowWidth; + if (rowWidth > 0) { + this->LogicLayer[index - 1] = L_BORDER_EDGE; + } + this->LogicLayer[index] = L_BORDER; + index++; + } + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/setupMovementDirectionTranslationMatrix.cpp b/src/OpenSHC/Map/TileMapState/setupMovementDirectionTranslationMatrix.cpp new file mode 100644 index 0000000000..4db4ea925f --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/setupMovementDirectionTranslationMatrix.cpp @@ -0,0 +1,72 @@ +#include "../TileMapState.func.hpp" + +namespace OpenSHC { +namespace Map { + + // FUNCTION: STRONGHOLDCRUSADER 0x004F6B20 + void TileMapState::setupMovementDirectionTranslationMatrix() + { + /* + Ghidra rendered the two running values of the first loop as directionTranslationMatrix[199][4] + and [200][5]; in the original they are registers, and rows 199 and 200 are only written by + the block after the loop. Rows 0..198 count up in "step" and down in "counter", rows 201.. count + back down again. + */ + int step = 2; + int counter = 0; + for (int row = 0; row < 199; row++) { + this->directionTranslationMatrix[row][0] = counter - 1; + this->directionTranslationMatrix[row][3] = step + 2; + this->directionTranslationMatrix[row][4] = step + 1; + this->directionTranslationMatrix[row][1] = counter; + this->directionTranslationMatrix[row][5] = step; + this->directionTranslationMatrix[row][2] = 1; + this->directionTranslationMatrix[row][6] = -1; + this->directionTranslationMatrix[row][7] = counter - 2; + this->yArray1[row] = step; + counter = counter - 2; + step = step + 2; + } + + this->directionTranslationMatrix[199][1] = 2 - step; + this->directionTranslationMatrix[199][4] = step; + this->directionTranslationMatrix[199][6] = -1; + this->directionTranslationMatrix[199][2] = 1; + this->directionTranslationMatrix[199][3] = step + 1; + this->directionTranslationMatrix[199][0] = 1 - step; + this->directionTranslationMatrix[199][7] = -step; + this->directionTranslationMatrix[199][5] = step - 1; + this->yArray1[199] = step; + this->directionTranslationMatrix[200][0] = -step; + this->directionTranslationMatrix[200][1] = 1 - step; + this->directionTranslationMatrix[200][2] = 1; + this->directionTranslationMatrix[200][3] = step; + this->directionTranslationMatrix[200][4] = step - 1; + this->directionTranslationMatrix[200][5] = step - 2; + this->directionTranslationMatrix[200][6] = -1; + this->directionTranslationMatrix[200][7] = -1 - step; + this->yArray1[200] = step; + + if (step - 2 > 0) { + int lowerStep = step - 2; + int lowerCounter = -2 - lowerStep; + int lowerRow = 201; + do { + this->directionTranslationMatrix[lowerRow][0] = lowerCounter + 1; + this->directionTranslationMatrix[lowerRow][1] = lowerCounter + 2; + this->directionTranslationMatrix[lowerRow][4] = lowerStep - 1; + this->directionTranslationMatrix[lowerRow][3] = lowerStep; + this->directionTranslationMatrix[lowerRow][7] = lowerCounter; + this->directionTranslationMatrix[lowerRow][2] = 1; + this->directionTranslationMatrix[lowerRow][5] = lowerStep - 2; + this->directionTranslationMatrix[lowerRow][6] = -1; + this->yArray1[lowerRow] = lowerStep; + lowerStep = lowerStep - 2; + lowerCounter = lowerCounter + 2; + lowerRow++; + } while (lowerStep > 0); + } + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/setupTileMapSections.cpp b/src/OpenSHC/Map/TileMapState/setupTileMapSections.cpp new file mode 100644 index 0000000000..6047a48d28 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/setupTileMapSections.cpp @@ -0,0 +1,84 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/IO/LowLevelMemory.func.hpp" +#include "OpenSHC/Map/MapConstants.hpp" +#include "OpenSHC/Random/RNG.func.hpp" + +#include "OpenSHC/Globals/DAT_LowLevelMemory.hpp" +#include "OpenSHC/Globals/SEC_RNG.hpp" + +namespace OpenSHC { +namespace Map { + + // FUNCTION: STRONGHOLDCRUSADER 0x00511DF0 + void TileMapState::setupTileMapSections() + { + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + sizeof(this->GfxLayer), '\0', this->GfxLayer); + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + sizeof(this->AlphaGFXLayer), '\0', this->AlphaGFXLayer); + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + sizeof(this->ConstructionGFXLayer), '\0', this->ConstructionGFXLayer); + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + sizeof(this->PillarGFXLayer), '\0', this->PillarGFXLayer); + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + sizeof(this->WallGFXLayer), '\0', this->WallGFXLayer); + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + sizeof(this->FloatingLayer), '\0', this->FloatingLayer); + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + sizeof(this->UnitLayer), '\0', this->UnitLayer); + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + sizeof(this->EntityLayer), '\0', this->EntityLayer); + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + sizeof(this->EntityLayerLT25), '\0', this->EntityLayerLT25); + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + sizeof(this->BuildingLayer), '\0', this->BuildingLayer); + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + sizeof(this->LogicLayer), '\0', this->LogicLayer); + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + sizeof(this->Logic2Layer), '\0', this->Logic2Layer); + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + sizeof(this->ChangedLayer), '\0', this->ChangedLayer); + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + sizeof(this->OrganismLayer), '\0', this->OrganismLayer); + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + sizeof(this->DamageLayer), '\0', this->DamageLayer); + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + sizeof(this->MacroLayer), '\0', this->MacroLayer); + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + sizeof(this->HeightLayer), '\0', this->HeightLayer); + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + sizeof(this->DefaultHeightLayer), '\0', this->DefaultHeightLayer); + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + sizeof(this->ShowHiLayer), '\0', this->ShowHiLayer); + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + sizeof(this->MiscDisplayLayer), '\0', this->MiscDisplayLayer); + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + sizeof(this->LuminesenceLayer), '\0', this->LuminesenceLayer); + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + sizeof(this->WallOwnerLayer), '\0', this->WallOwnerLayer); + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + sizeof(this->BuildingWasLayer), '\0', this->BuildingWasLayer); + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + sizeof(this->OccupancyLayer), '\0', this->OccupancyLayer); + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + sizeof(this->AIZoneLayer), '\0', this->AIZoneLayer); + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + sizeof(this->AIInfoLayer), '\0', this->AIInfoLayer); + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + sizeof(this->unitDeathHeatMap), '\0', this->unitDeathHeatMap); + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + sizeof(this->SEC_TileMap1104), '\0', this->SEC_TileMap1104); + MACRO_CALL_MEMBER(OpenSHC::IO::LowLevelMemory_Func::fillMemory_ByteValue, DAT_LowLevelMemory::ptr)( + sizeof(this->SEC_PathfindingCostTileMap1105), '\0', this->SEC_PathfindingCostTileMap1105); + + for (int tile = 0; tile < MC_MAP_TILES_COUNT; tile++) { + MACRO_CALL_MEMBER(OpenSHC::Random::RNG_Func::nextRandomNumber2, SEC_RNG::ptr)(); + this->RandomLayer[tile] = SEC_RNG::instance.currentNumber2; + } + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::changeMapOrientation, this)(0); + this->DAT_FutureMapOrientation = 8; + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/spawnEraserTileEffect.cpp b/src/OpenSHC/Map/TileMapState/spawnEraserTileEffect.cpp new file mode 100644 index 0000000000..9fcd04a504 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/spawnEraserTileEffect.cpp @@ -0,0 +1,63 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Map/Entities/EntityState.func.hpp" +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" +#include "OpenSHC/UI/MinimapViewState.func.hpp" +#include "OpenSHC/Map/Entities/EntityType.hpp" + +#include "OpenSHC/Globals/DAT_EntityState.hpp" +#include "OpenSHC/Globals/DAT_MinimapViewState.hpp" +#include "OpenSHC/Globals/DAT_PathFindingState.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_BUILDING; + using OpenSHC::Map::LogicHelpers::L_CRENEL; + using OpenSHC::Map::LogicHelpers::L_CRENEL_VARIATIONUnk; + using OpenSHC::Map::LogicHelpers::L_STAIRS; + using OpenSHC::Map::LogicHelpers::L_UNKNOWN_WALL_RELATED; + using OpenSHC::Map::LogicHelpers::L_WALL_OR_GATEHOUSE; + + using OpenSHC::Map::Entities::EntityType; + + // FUNCTION: STRONGHOLDCRUSADER 0x004F9F00 + void TileMapState::spawnEraserTileEffect(undefined4 param_1, int tile) + { + uint y = DAT_ViewportRenderState::instance.tileTranslationMatrix_YComponent[tile]; + int rowTile = DAT_ViewportRenderState::instance.translationMatrix[y].addXgetTile; + this->MiscDisplayLayer[tile] = this->MiscDisplayLayer[tile] & 0xfbff; + if (this->UnitLayer[tile] != 0) { + return; + } + + this->HeightLayer[tile] = this->DefaultHeightLayer[tile]; + MACRO_CALL_MEMBER(OpenSHC::Map::Entities::EntityState_Func::destroyEntitiesOnTile, DAT_EntityState::ptr)(tile); + this->LogicLayer[tile] = this->LogicLayer[tile] + & ~(L_WALL_OR_GATEHOUSE | L_CRENEL | L_BUILDING | L_STAIRS | L_UNKNOWN_WALL_RELATED + | L_CRENEL_VARIATIONUnk); + int microY = DAT_ViewportRenderState::instance.tileTranslationMatrix_YComponent[tile] * 8; + int microX + = (tile + - DAT_ViewportRenderState::instance + .translationMatrix[DAT_ViewportRenderState::instance.tileTranslationMatrix_YComponent[tile]] + .addXgetTile) + * 8; + MACRO_CALL_MEMBER(OpenSHC::Map::Entities::EntityState_Func::spawnProjectileEntity, DAT_EntityState::ptr)(0, 0, + 0, microX, microY, DAT_TileMapState::instance.DefaultHeightLayer[tile], microX + 1, microY + 1, + DAT_TileMapState::instance.DefaultHeightLayer[tile], (EntityType)0x1e, 0); + this->BuildingWasLayer[tile] = 0; + this->DamageLayer[tile] = 0; + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::updatePathLinkagesInAllEightDirections, + DAT_PathFindingState::ptr)(y, tile); + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::updateWalkAndPathLayer, + DAT_PathFindingState::ptr)(9, tile - rowTile, y); + MACRO_CALL_MEMBER(OpenSHC::UI::MinimapViewState_Func::triggerMinimapRedraw, DAT_MinimapViewState::ptr)(1); + DAT_PathFindingState::instance.toggleUpdateSeparateAreaTileMap = 1; + DAT_TileMapState::instance.field204_0x554a30 = 1; + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/spawnFloatingNumberAroundTile.cpp b/src/OpenSHC/Map/TileMapState/spawnFloatingNumberAroundTile.cpp new file mode 100644 index 0000000000..6fa56bb970 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/spawnFloatingNumberAroundTile.cpp @@ -0,0 +1,47 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Rendering/ViewportRenderState.func.hpp" +#include "OpenSHC/IO/Graphics/GmID.hpp" + +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_BUILDING; + using OpenSHC::Map::LogicHelpers::L_KEEP_NON_MANOR_HOUSE; + using OpenSHC::Map::LogicHelpers::L_WALL_OR_GATEHOUSE; + + // FUNCTION: STRONGHOLDCRUSADER 0x004FB3F0 + void TileMapState::spawnFloatingNumberAroundTile(int x, int y, int type) + { + int radius = type / 2; + int xBase = x - radius; + int yBase = y - radius; + int index = 0; + int xOffset = DAT_TerrainDefinedData::instance.field2343_0x2764[radius * 60].x; + if (xOffset == -1) { + return; + } + + do { + int yOffset = DAT_TerrainDefinedData::instance.field2343_0x2764[radius * 60 + index].y; + int tileUnk = DAT_ViewportRenderState::instance.translationMatrix[yOffset + yBase].addXgetTile + xOffset + xBase; + if ((this->LogicLayer[tileUnk] & (L_WALL_OR_GATEHOUSE | L_BUILDING | L_KEEP_NON_MANOR_HOUSE)) == 0 + && (index & 1) == 0) { + int frame + = ((int)DAT_TileMapState::instance.cursorOverlayAnimationFrame + yOffset + xOffset + index + yBase + xBase - 1) + % 16; + MACRO_CALL_MEMBER(OpenSHC::Rendering::ViewportRenderState_Func::createFloatingLayerElement, + DAT_ViewportRenderState::ptr)( + OpenSHC::IO::Graphics::GID_FLOATS_NEW, frame + 0xe5, 16, 14, tileUnk, 0x100021); + } + index++; + xOffset = DAT_TerrainDefinedData::instance.field2343_0x2764[radius * 60 + index].x; + } while (xOffset != -1); + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/stampBuildingOntoTileMap.cpp b/src/OpenSHC/Map/TileMapState/stampBuildingOntoTileMap.cpp new file mode 100644 index 0000000000..81dffa90f2 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/stampBuildingOntoTileMap.cpp @@ -0,0 +1,41 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Map/Buildings/BuildingsState.func.hpp" + +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_BUILDING; + + // FUNCTION: STRONGHOLDCRUSADER 0x00507060 + void TileMapState::stampBuildingOntoTileMap(int param_1, uint param_2, uint param_3, undefined4 param_4, + undefined4 param_5, uint param_6, undefined4 param_7, undefined4 param_8) + { + int buildingID = MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::setupBuildingData, DAT_BuildingsState::ptr)( + param_1, param_2, param_3, param_8, (BuildingType)(short)param_4, param_6, param_1, (short)param_5); + this->placedBuildingID = buildingID; + int buildingSizeTileIndex = 0; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)( + buildingSizeTileIndex, param_6); + int tile = DAT_ViewportRenderState::instance.translationMatrix[this->buildingY + param_3].addXgetTile + + this->buildingX + param_2; + if (buildingSizeTileIndex < 36) { + DAT_BuildingsState::instance.buildings[buildingID].tileRefs[buildingSizeTileIndex] = tile; + } + this->HeightLayer[tile] = (byte)param_8; + this->LogicLayer[tile] = this->LogicLayer[tile] | L_BUILDING; + this->BuildingLayer[tile] = (short)buildingID; + buildingSizeTileIndex++; + this->ChangedLayer[tile] = 2; + } while (buildingSizeTileIndex < this->constructionTileCount); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::setMiscDisplayLayer, this)(buildingID); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::updatePathLinkagesForBuilding, this)(buildingID); + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/storeMinAndMaxHeightOfArea.cpp b/src/OpenSHC/Map/TileMapState/storeMinAndMaxHeightOfArea.cpp new file mode 100644 index 0000000000..5cc0b11423 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/storeMinAndMaxHeightOfArea.cpp @@ -0,0 +1,43 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + + // FUNCTION: STRONGHOLDCRUSADER 0x004F9980 + void TileMapState::storeMinAndMaxHeightOfArea(uint x, uint y, int buildingWidthAndHeight) + { + this->buildingMinHeight = 1000; + this->buildingMaxHeight = 0; + if (x > 399 || y > 399) { + return; + } + if (DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[y * 400 + x] == 0) { + return; + } + + int buildingSizeTileIndex = 0; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)( + buildingSizeTileIndex, buildingWidthAndHeight); + uint footprintY = this->buildingY + y; + uint footprintX = this->buildingX + x; + if (footprintX <= 399 && footprintY <= 399 + && DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[footprintY * 400 + footprintX] != 0) { + uint height + = this->HeightLayer[DAT_ViewportRenderState::instance.translationMatrix[footprintY].addXgetTile + + this->buildingX + x]; + if ((int)height > this->buildingMaxHeight) { + this->buildingMaxHeight = height; + } + if ((int)height < this->buildingMinHeight) { + this->buildingMinHeight = height; + } + } + buildingSizeTileIndex++; + } while (buildingSizeTileIndex < this->constructionTileCount); + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/swapMoatOwnership.cpp b/src/OpenSHC/Map/TileMapState/swapMoatOwnership.cpp new file mode 100644 index 0000000000..d94c0b2e1a --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/swapMoatOwnership.cpp @@ -0,0 +1,22 @@ +#include "../TileMapState.func.hpp" + +namespace OpenSHC { +namespace Map { + + // FUNCTION: STRONGHOLDCRUSADER 0x00500790 + void TileMapState::swapMoatOwnership(int param_1, int param_2) + { + for (int moatID = 1; moatID < 16000; moatID++) { + if (this->moats[moatID].owner == 0) { + continue; + } + if (this->moats[moatID].owner == param_1) { + this->moats[moatID].owner = (char)param_2; + } else if (this->moats[moatID].owner == param_2) { + this->moats[moatID].owner = (char)param_1; + } + } + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/swapPitchOwnership.cpp b/src/OpenSHC/Map/TileMapState/swapPitchOwnership.cpp new file mode 100644 index 0000000000..e53a5e4462 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/swapPitchOwnership.cpp @@ -0,0 +1,22 @@ +#include "../TileMapState.func.hpp" + +namespace OpenSHC { +namespace Map { + + // FUNCTION: STRONGHOLDCRUSADER 0x00500940 + void TileMapState::swapPitchOwnership(int param_1, int param_2) + { + for (int pitchDitchID = 1; pitchDitchID < 4000; pitchDitchID++) { + if (this->pitchDitches[pitchDitchID].owner == 0) { + continue; + } + if (this->pitchDitches[pitchDitchID].owner == param_1) { + this->pitchDitches[pitchDitchID].owner = (short)param_2; + } else if (this->pitchDitches[pitchDitchID].owner == param_2) { + this->pitchDitches[pitchDitchID].owner = (short)param_1; + } + } + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/swapWallOwnership.cpp b/src/OpenSHC/Map/TileMapState/swapWallOwnership.cpp new file mode 100644 index 0000000000..42f9c13e46 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/swapWallOwnership.cpp @@ -0,0 +1,58 @@ +#include "../TileMapState.func.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_WALL_OR_GATEHOUSE; + + // FUNCTION: STRONGHOLDCRUSADER 0x004F9220 + void TileMapState::swapWallOwnership(int playerID, int otherPlayerID) + { + for (int tileUnk = 0; tileUnk < 80400; tileUnk += 6) { + if ((this->LogicLayer[tileUnk + 0] & L_WALL_OR_GATEHOUSE) != 0) { + if ((this->WallOwnerLayer[tileUnk + 0] & 7) + 1 == playerID) { + this->WallOwnerLayer[tileUnk + 0] = this->WallOwnerLayer[tileUnk + 0] & 0xf8 | (char)otherPlayerID - 1U; + } else if ((this->WallOwnerLayer[tileUnk + 0] & 7) + 1 == otherPlayerID) { + this->WallOwnerLayer[tileUnk + 0] = this->WallOwnerLayer[tileUnk + 0] & 0xf8 | (char)playerID - 1U; + } + } + if ((this->LogicLayer[tileUnk + 1] & L_WALL_OR_GATEHOUSE) != 0) { + if ((this->WallOwnerLayer[tileUnk + 1] & 7) + 1 == playerID) { + this->WallOwnerLayer[tileUnk + 1] = this->WallOwnerLayer[tileUnk + 1] & 0xf8 | (char)otherPlayerID - 1U; + } else if ((this->WallOwnerLayer[tileUnk + 1] & 7) + 1 == otherPlayerID) { + this->WallOwnerLayer[tileUnk + 1] = this->WallOwnerLayer[tileUnk + 1] & 0xf8 | (char)playerID - 1U; + } + } + if ((this->LogicLayer[tileUnk + 2] & L_WALL_OR_GATEHOUSE) != 0) { + if ((this->WallOwnerLayer[tileUnk + 2] & 7) + 1 == playerID) { + this->WallOwnerLayer[tileUnk + 2] = this->WallOwnerLayer[tileUnk + 2] & 0xf8 | (char)otherPlayerID - 1U; + } else if ((this->WallOwnerLayer[tileUnk + 2] & 7) + 1 == otherPlayerID) { + this->WallOwnerLayer[tileUnk + 2] = this->WallOwnerLayer[tileUnk + 2] & 0xf8 | (char)playerID - 1U; + } + } + if ((this->LogicLayer[tileUnk + 3] & L_WALL_OR_GATEHOUSE) != 0) { + if ((this->WallOwnerLayer[tileUnk + 3] & 7) + 1 == playerID) { + this->WallOwnerLayer[tileUnk + 3] = this->WallOwnerLayer[tileUnk + 3] & 0xf8 | (char)otherPlayerID - 1U; + } else if ((this->WallOwnerLayer[tileUnk + 3] & 7) + 1 == otherPlayerID) { + this->WallOwnerLayer[tileUnk + 3] = this->WallOwnerLayer[tileUnk + 3] & 0xf8 | (char)playerID - 1U; + } + } + if ((this->LogicLayer[tileUnk + 4] & L_WALL_OR_GATEHOUSE) != 0) { + if ((this->WallOwnerLayer[tileUnk + 4] & 7) + 1 == playerID) { + this->WallOwnerLayer[tileUnk + 4] = this->WallOwnerLayer[tileUnk + 4] & 0xf8 | (char)otherPlayerID - 1U; + } else if ((this->WallOwnerLayer[tileUnk + 4] & 7) + 1 == otherPlayerID) { + this->WallOwnerLayer[tileUnk + 4] = this->WallOwnerLayer[tileUnk + 4] & 0xf8 | (char)playerID - 1U; + } + } + if ((this->LogicLayer[tileUnk + 5] & L_WALL_OR_GATEHOUSE) != 0) { + if ((this->WallOwnerLayer[tileUnk + 5] & 7) + 1 == playerID) { + this->WallOwnerLayer[tileUnk + 5] = this->WallOwnerLayer[tileUnk + 5] & 0xf8 | (char)otherPlayerID - 1U; + } else if ((this->WallOwnerLayer[tileUnk + 5] & 7) + 1 == otherPlayerID) { + this->WallOwnerLayer[tileUnk + 5] = this->WallOwnerLayer[tileUnk + 5] & 0xf8 | (char)playerID - 1U; + } + } + } + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/triggerLoweredView.cpp b/src/OpenSHC/Map/TileMapState/triggerLoweredView.cpp new file mode 100644 index 0000000000..a7f46930c2 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/triggerLoweredView.cpp @@ -0,0 +1,61 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Map/Units/UnitLogicState.hpp" +#include "OpenSHC/Map/Units/UnitType.hpp" + +#include "OpenSHC/Globals/DAT_GameCore.hpp" +#include "OpenSHC/Globals/DAT_UnitsState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::Units::UnitLogicState; + using OpenSHC::Map::Units::UnitType; + + // FUNCTION: STRONGHOLDCRUSADER 0x004F6FD0 + void TileMapState::triggerLoweredView(int param_1) + { + int view = 2; + if (this->flatViewToggleValue2 == 0) { + view = param_1; + } + if (this->refreshCertainTileMap_old == view) { + return; + } + this->counter1 = 0; + this->refreshCertainTileMap = view; + if (view != 3) { + return; + } + if (DAT_GameCore::instance.gamePausedLogical != 0) { + return; + } + + for (int unitID = 1; unitID < (int)DAT_UnitsState::instance.maxUnitCount; unitID++) { + if (DAT_UnitsState::instance.units[unitID].logicalState == OpenSHC::Map::Units::ULS_INVISIBLE) { + continue; + } + if (DAT_UnitsState::instance.units[unitID].unitType != OpenSHC::Map::Units::UT_DRUNK + && DAT_UnitsState::instance.units[unitID].unitType != OpenSHC::Map::Units::UT_RABBIT + && DAT_UnitsState::instance.units[unitID].unitType != OpenSHC::Map::Units::UT_HUNTERDOG + && DAT_UnitsState::instance.units[unitID].unitType != OpenSHC::Map::Units::UT_JESTER + && DAT_UnitsState::instance.units[unitID].unitType != OpenSHC::Map::Units::UT_CHICKEN + && DAT_UnitsState::instance.units[unitID].unitType != OpenSHC::Map::Units::UT_CHILD + && DAT_UnitsState::instance.units[unitID].unitType != OpenSHC::Map::Units::UT_JUGGLER + && DAT_UnitsState::instance.units[unitID].unitType != OpenSHC::Map::Units::UT_FIREEATER) { + continue; + } + + int height = (DAT_UnitsState::instance.units[unitID].buildingHeight + + DAT_UnitsState::instance.units[unitID].terrainOrClimbHeight) + / 10; + if (height > 14) { + height = 14; + } + DAT_UnitsState::instance.units[unitID].heightDiv10 = (char)height; + DAT_UnitsState::instance.units[unitID].field_0x83 = 0; + } + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/unmarkBuildingFootprintFlag.cpp b/src/OpenSHC/Map/TileMapState/unmarkBuildingFootprintFlag.cpp new file mode 100644 index 0000000000..f4994b2580 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/unmarkBuildingFootprintFlag.cpp @@ -0,0 +1,25 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_PLAIN1_AND_FARM; + + // FUNCTION: STRONGHOLDCRUSADER 0x004FAD20 + void TileMapState::unmarkBuildingFootprintFlag(int param_1, int param_2, int param_3) + { + int buildingSizeTileIndex = 0; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)( + buildingSizeTileIndex, param_3); + buildingSizeTileIndex++; + int tile = DAT_ViewportRenderState::instance.translationMatrix[this->buildingY + param_2].addXgetTile + + this->buildingX + param_1; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_PLAIN1_AND_FARM; + } while (buildingSizeTileIndex < this->constructionTileCount); + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/updateAreaBasedOnSurrounding.cpp b/src/OpenSHC/Map/TileMapState/updateAreaBasedOnSurrounding.cpp new file mode 100644 index 0000000000..6cb6e376a0 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/updateAreaBasedOnSurrounding.cpp @@ -0,0 +1,31 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Map/Buildings/BuildingsState.func.hpp" + +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + + // FUNCTION: STRONGHOLDCRUSADER 0x004FAA30 + void TileMapState::updateAreaBasedOnSurrounding(int x, int y, int buildingSize) + { + int buildingSizeTileIndex = 0; + int area + = MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::findAccessibleAreaNearBuildingLocation, + DAT_BuildingsState::ptr)(x, y, buildingSize); + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)( + buildingSizeTileIndex, buildingSize); + int tileUnk = DAT_ViewportRenderState::instance.translationMatrix[this->buildingY + y].addXgetTile + + this->buildingX + x; + if (this->PathConnectionLayer[tileUnk] == 0) { + this->PathConnectionLayer[tileUnk] = (ushort)area; + } + buildingSizeTileIndex++; + } while (buildingSizeTileIndex < this->constructionTileCount); + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/updateBuildingGraphicsLayer.cpp b/src/OpenSHC/Map/TileMapState/updateBuildingGraphicsLayer.cpp new file mode 100644 index 0000000000..f90e7497d4 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/updateBuildingGraphicsLayer.cpp @@ -0,0 +1,326 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Game/GameMode2.hpp" +#include "OpenSHC/Map/Buildings/BuildingType.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" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" +#include "OpenSHC/Globals/GMTotalPicturesProcessed.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Game::GameMode2; + using OpenSHC::Map::Buildings::BuildingType; + + // FUNCTION: STRONGHOLDCRUSADER 0x00506370 + void TileMapState::updateBuildingGraphicsLayer(int buildingID) + { + ushort buildingXPos = DAT_BuildingsState::instance.buildings[buildingID].x; + ushort buildingYPos = DAT_BuildingsState::instance.buildings[buildingID].y; + DAT_BuildingsState::instance.buildings[buildingID].useOffsetGraphics = 0; + if (this->refreshRelatedOne == 0 && DAT_BuildingsState::instance.buildings[buildingID].gfxOffset != 0) { + DAT_BuildingsState::instance.buildings[buildingID].useOffsetGraphics = 1; + } + int stored = DAT_BuildingsState::instance.buildings[buildingID].currentNumberOfResource + - (int)DAT_BuildingsState::instance.buildings[buildingID].someResourceNumber; + + int index = 0; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)( + index, DAT_BuildingsState::instance.buildings[buildingID].widthOrHeight); + int tile + = DAT_ViewportRenderState::instance.translationMatrix[this->buildingY + (short)buildingYPos].addXgetTile + + (short)buildingXPos + this->buildingX; + if (this->disableElevationRendering != 0) { + /* the placement overlay replaces every building graphic with its outline */ + this->AlphaGFXLayer[tile] = 0; + this->GfxLayer[tile] + = ((short)DAT_TerrainDefinedData::instance + .BrushSizeArray[DAT_BuildingsState::instance.buildings[buildingID].widthOrHeight + 7] + + (short)this->buildingRotationRelatedValue + (short)GMTotalPicturesProcessed::instance[0x9d]) + - 1; + } else if (DAT_BuildingsState::instance.buildings[buildingID].buildingType + == OpenSHC::Map::Buildings::BT_STOCKPILE + || DAT_BuildingsState::instance.buildings[buildingID].buildingType + == OpenSHC::Map::Buildings::BT_QUARRYSTOCKPILE) { + /* a stockpile's pile grows with what is stored on it */ + if (stored < 1) { + this->GfxLayer[tile] = (short)this->buildingRotationRelatedValue + + (short)GMTotalPicturesProcessed::instance[0xf] + 4; + } else { + short resource = DAT_BuildingsState::instance.buildings[buildingID].currentStoredResourceType; + short pile; + if (DAT_TerrainDefinedData::instance.field870_0x8b4[resource] == 2) { + int remaining + = DAT_BuildingsState::instance.buildings[buildingID].currentLimitOfResource - stored; + pile = (short)this->buildingRotationRelatedValue + + ((short)(remaining / 4) + ((ushort)remaining & 3) * 0xc) * 4; + } else if (DAT_TerrainDefinedData::instance.field870_0x8b4[resource] == 0) { + pile = (short)this->buildingRotationRelatedValue + -4 + (short)stored * 4; + } else { + pile = (short)this->buildingRotationRelatedValue + + ((short)DAT_BuildingsState::instance.buildings[buildingID].currentLimitOfResource + - (short)stored) + * 4; + } + this->GfxLayer[tile] = (short)GMTotalPicturesProcessed::instance[0xf] + + (short)DAT_TerrainDefinedData::instance.field865_0x84c[resource] - 1 + pile; + } + } else if (DAT_BuildingsState::instance.buildings[buildingID].buildingType + == OpenSHC::Map::Buildings::BT_MERCENARYPOST + || DAT_BuildingsState::instance.buildings[buildingID].buildingType + == OpenSHC::Map::Buildings::BT_BARRACKS + || DAT_BuildingsState::instance.buildings[buildingID].buildingType + == OpenSHC::Map::Buildings::BT_OUTPOST_EUROPEAN) { + this->GfxLayer[tile] = ((short)GMTotalPicturesProcessed::instance + [(short)DAT_BuildingsState::instance.buildings[buildingID].spriteSheetID] + + (short)DAT_BuildingsState::instance.buildings[buildingID].spriteID + + (short)this->buildingRotationRelatedValue) + - 1; + } else if (DAT_BuildingsState::instance.buildings[buildingID].buildingType + == OpenSHC::Map::Buildings::BT_KEEPDOOR_LEFT + || DAT_BuildingsState::instance.buildings[buildingID].buildingType + == OpenSHC::Map::Buildings::BT_KEEPDOOR_RIGHT) { + /* a side door faces along the keep's axis, so its graphic follows the map rotation */ + uint facing = this->mapOrientation; + if (DAT_BuildingsState::instance.buildings[buildingID].orientation == 6 + || DAT_BuildingsState::instance.buildings[buildingID].orientation == 2) { + facing = (this->mapOrientation + 2) % 8; + } + if (DAT_BuildingsState::instance.buildings[buildingID].useOffsetGraphics == 0) { + if (facing == 2 || facing == 6) { + this->GfxLayer[tile] + = (short)GMTotalPicturesProcessed::instance + [(short)DAT_BuildingsState::instance.buildings[buildingID].spriteSheetID] + + (short)DAT_BuildingsState::instance.buildings[buildingID] + .unknownManorHouseOrStoneKeepRelated + + (short)DAT_BuildingsState::instance.buildings[buildingID].spriteID; + } else { + this->GfxLayer[tile] + = ((short)GMTotalPicturesProcessed::instance + [(short)DAT_BuildingsState::instance.buildings[buildingID].spriteSheetID] + + (short)DAT_BuildingsState::instance.buildings[buildingID] + .unknownManorHouseOrStoneKeepRelated + + (short)DAT_BuildingsState::instance.buildings[buildingID].spriteID) + - 1; + } + } else if (facing == 2 || facing == 6) { + this->GfxLayer[tile] = (short)GMTotalPicturesProcessed::instance + [(short)DAT_BuildingsState::instance.buildings[buildingID].spriteSheetID] + + (short)DAT_BuildingsState::instance.buildings[buildingID].gfxOffset; + } else { + this->GfxLayer[tile] + = ((short)GMTotalPicturesProcessed::instance + [(short)DAT_BuildingsState::instance.buildings[buildingID].spriteSheetID] + + (short)DAT_BuildingsState::instance.buildings[buildingID].gfxOffset) + - 1; + } + } else if (DAT_BuildingsState::instance.buildings[buildingID].buildingType + == OpenSHC::Map::Buildings::BT_KEEPDOOR) { + if (DAT_BuildingsState::instance.buildings[buildingID].useOffsetGraphics == 0) { + if (this->mapOrientation != 2 && this->mapOrientation != 6) { + this->GfxLayer[tile] + = ((short)GMTotalPicturesProcessed::instance + [(short)DAT_BuildingsState::instance.buildings[buildingID].spriteSheetID] + + (short)DAT_BuildingsState::instance.buildings[buildingID] + .unknownManorHouseOrStoneKeepRelated + + (short)DAT_BuildingsState::instance.buildings[buildingID].spriteID) + - 1; + } else { + this->GfxLayer[tile] + = (short)GMTotalPicturesProcessed::instance + [(short)DAT_BuildingsState::instance.buildings[buildingID].spriteSheetID] + + (short)DAT_BuildingsState::instance.buildings[buildingID] + .unknownManorHouseOrStoneKeepRelated + + (short)DAT_BuildingsState::instance.buildings[buildingID].spriteID; + } + } else { + this->GfxLayer[tile] + = ((short)GMTotalPicturesProcessed::instance + [(short)DAT_BuildingsState::instance.buildings[buildingID].spriteSheetID] + + (short)DAT_BuildingsState::instance.buildings[buildingID] + .unknownManorHouseOrStoneKeepRelated + + (short)DAT_BuildingsState::instance.buildings[buildingID].gfxOffset) + - 1; + } + } else if (DAT_BuildingsState::instance.buildings[buildingID].buildingType + == OpenSHC::Map::Buildings::BT_GATEHOUSELARGE + || DAT_BuildingsState::instance.buildings[buildingID].buildingType + == OpenSHC::Map::Buildings::BT_GATEHOUSESMALL + || DAT_BuildingsState::instance.buildings[buildingID].buildingType + == OpenSHC::Map::Buildings::BT_WOODGATE1) { + int variation; + if (this->mapOrientation == 2 || this->mapOrientation == 6) { + variation = (DAT_BuildingsState::instance.buildings[buildingID].buildingVariation == 0x50) + 0x50; + } else { + variation = DAT_BuildingsState::instance.buildings[buildingID].buildingVariation; + } + if (DAT_BuildingsState::instance.buildings[buildingID].useOffsetGraphics == 0) { + if (variation == 0x50) { + this->GfxLayer[tile] + = ((short)GMTotalPicturesProcessed::instance + [(short)DAT_BuildingsState::instance.buildings[buildingID].spriteSheetID] + + (short)DAT_BuildingsState::instance.buildings[buildingID].spriteID + + (short)this->buildingRotationRelatedValue) + - 1; + } else { + this->GfxLayer[tile] + = (((short)GMTotalPicturesProcessed::instance + [(short)DAT_BuildingsState::instance.buildings[buildingID].spriteSheetID] + + (short)DAT_BuildingsState::instance.buildings[buildingID].gfxOffset2) + + (short)this->buildingRotationRelatedValue) + - 1; + } + } else if (variation != 0x50) { + this->GfxLayer[tile] + = ((short)GMTotalPicturesProcessed::instance + [(short)DAT_BuildingsState::instance.buildings[buildingID].spriteSheetID] + + (short)DAT_BuildingsState::instance.buildings[buildingID].gfxOffset3 + + (short)this->buildingRotationRelatedValue) + - 1; + } else { + this->GfxLayer[tile] + = (((short)GMTotalPicturesProcessed::instance + [(short)DAT_BuildingsState::instance.buildings[buildingID].spriteSheetID] + + (short)DAT_BuildingsState::instance.buildings[buildingID].gfxOffset) + + (short)this->buildingRotationRelatedValue) + - 1; + } + } else if (DAT_BuildingsState::instance.buildings[buildingID].buildingType + == OpenSHC::Map::Buildings::BT_MANORHOUSE) { + int variation = 0x50; + if (this->mapOrientation == 2 || this->mapOrientation == 6) { + variation = 0x51; + } + if (DAT_BuildingsState::instance.buildings[buildingID].useOffsetGraphics != 0) { + if (variation == 0x50) { + this->GfxLayer[tile] + = (((short)GMTotalPicturesProcessed::instance + [(short)DAT_BuildingsState::instance.buildings[buildingID].spriteSheetID] + + (short)DAT_BuildingsState::instance.buildings[buildingID].gfxOffset) + + (short)this->buildingRotationRelatedValue) + - 1; + } else { + this->GfxLayer[tile] + = (short)GMTotalPicturesProcessed::instance + [(short)DAT_BuildingsState::instance.buildings[buildingID].spriteSheetID] + + (short)this->buildingRotationRelatedValue + 0x298; + } + } else if (variation == 0x50) { + this->GfxLayer[tile] + = ((short)GMTotalPicturesProcessed::instance + [(short)DAT_BuildingsState::instance.buildings[buildingID].spriteSheetID] + + (short)DAT_BuildingsState::instance.buildings[buildingID].spriteID + + (short)this->buildingRotationRelatedValue) + - 1; + } else { + this->GfxLayer[tile] = (short)GMTotalPicturesProcessed::instance + [(short)DAT_BuildingsState::instance.buildings[buildingID].spriteSheetID] + + (short)this->buildingRotationRelatedValue + 0x236; + } + } else if (DAT_BuildingsState::instance.buildings[buildingID].buildingType + == OpenSHC::Map::Buildings::BT_DRAWBRIDGE) { + int plank + = DAT_TerrainDefinedData::instance + .field2336_0x1fec[(int)DAT_BuildingsState::instance.buildings[buildingID].buildingVariation + / 2][index]; + if (plank != 0) { + this->GfxLayer[tile] = (short)GMTotalPicturesProcessed::instance + [(short)DAT_BuildingsState::instance.buildings[buildingID].spriteSheetID] + + (short)plank + 0x61e; + } else if (MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::returnOwnedMoatAtTile, this)(tile) == 0) { + this->GfxLayer[tile] = ((byte)this->RandomLayer[tile] & 3) + + (ushort)this->LuminesenceLayer[tile] * 4 + (short)GMTotalPicturesProcessed::instance[2]; + } else { + this->GfxLayer[tile] = ((byte)this->RandomLayer[tile] & 3) + + (this->LuminesenceLayer[tile] + 0x33) * 4 + (short)GMTotalPicturesProcessed::instance[5]; + } + } else if ((DAT_BuildingsState::instance.buildings[buildingID].buildingType + != OpenSHC::Map::Buildings::BT_KILLINGPIT + || DAT_BuildingsState::instance.buildings[buildingID].state > 0 + || DAT_GameState::instance.mapAndTime + .playerTeams[DAT_BuildingsState::instance.buildings[buildingID].owner] + == DAT_GameState::instance.mapAndTime + .playerTeams[DAT_GameSynchronyState::instance.currentPlayerSlotID] + || DAT_GameCore::instance.gameMode_2 == OpenSHC::Game::GM_EDITOR) + && DAT_BuildingsState::instance.buildings[buildingID].buildingType + != OpenSHC::Map::Buildings::BT_SIEGETOWER_PLACED) { + /* a killing pit is invisible to anyone not on the owner's team */ + if (DAT_BuildingsState::instance.buildings[buildingID].buildingVariation == 0xf) { + if (DAT_BuildingsState::instance.buildings[buildingID].useOffsetGraphics != 0) { + this->GfxLayer[tile] + = ((short)GMTotalPicturesProcessed::instance + [(short)DAT_BuildingsState::instance.buildings[buildingID].spriteSheetID] + + (short)DAT_BuildingsState::instance.buildings[buildingID].gfxOffset + + (short)this->buildingRotationRelatedValue) + - 1; + } else if (DAT_BuildingsState::instance.buildings[buildingID].buildingIsVisuallyActive == 0) { + this->GfxLayer[tile] + = ((short)GMTotalPicturesProcessed::instance + [(short)DAT_BuildingsState::instance.buildings[buildingID].spriteSheetID] + + (short)DAT_BuildingsState::instance.buildings[buildingID] + .unknownManorHouseOrStoneKeepRelated + + (short)DAT_BuildingsState::instance.buildings[buildingID].spriteID + + (short)this->buildingRotationRelatedValue) + - 1; + } else { + this->GfxLayer[tile] + = ((short)GMTotalPicturesProcessed::instance + [(short)DAT_BuildingsState::instance.buildings[buildingID].spriteSheetID] + + (short)DAT_BuildingsState::instance.buildings[buildingID].visuallyActiveSpriteID + + (short)this->buildingRotationRelatedValue) + - 1; + } + this->AlphaGFXLayer[tile] + = ((short)GMTotalPicturesProcessed::instance + [(short)DAT_BuildingsState::instance.buildings[buildingID].spriteSheetID] + + (short)DAT_BuildingsState::instance.buildings[buildingID] + .unknownManorHouseOrStoneKeepRelated + + (short)DAT_BuildingsState::instance.buildings[buildingID].spriteID + + (short)this->buildingRotationRelatedValue) + - 1; + } else { + int relative + = DAT_BuildingsState::instance.buildings[buildingID].buildingVariation - this->mapOrientation; + if (relative < 0) { + relative = relative + 8; + } + short rotation = (short)relative; + short span; + if (DAT_BuildingsState::instance.buildings[buildingID].buildingVariation == 8) { + rotation = (short)DAT_BuildingsState::instance.buildings[buildingID].widthOrHeight; + span = rotation * 8; + } else { + span = (short)DAT_BuildingsState::instance.buildings[buildingID].widthOrHeight; + span = span * span; + } + short sprite; + if (DAT_BuildingsState::instance.buildings[buildingID].buildingIsVisuallyActive == 0) { + sprite = (short)DAT_BuildingsState::instance.buildings[buildingID].spriteID; + } else { + sprite = (short)DAT_BuildingsState::instance.buildings[buildingID].visuallyActiveSpriteID; + } + this->GfxLayer[tile] + = ((short)GMTotalPicturesProcessed::instance + [(short)DAT_BuildingsState::instance.buildings[buildingID].spriteSheetID] + + sprite + (short)this->buildingRotationRelatedValue + span * rotation) + - 1; + this->AlphaGFXLayer[tile] + = ((short)GMTotalPicturesProcessed::instance + [(short)DAT_BuildingsState::instance.buildings[buildingID].spriteSheetID] + + (short)DAT_BuildingsState::instance.buildings[buildingID].spriteID + + (short)this->buildingRotationRelatedValue + span * rotation) + - 1; + } + } + index++; + } while (index < this->constructionTileCount); + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/updateGFXLayers.cpp b/src/OpenSHC/Map/TileMapState/updateGFXLayers.cpp new file mode 100644 index 0000000000..6f22ba9df7 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/updateGFXLayers.cpp @@ -0,0 +1,360 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Map/Navigation/DirectionAlgorithmState.func.hpp" +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" +#include "OpenSHC/Rendering/ViewportRenderState.func.hpp" +#include "OpenSHC/Map/TileMapState/NeighbourFlagsAsm.hpp" + +#include "OpenSHC/Globals/DAT_DirectionAlgorithmState.hpp" +#include "OpenSHC/Globals/DAT_PathFindingState.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" +#include "OpenSHC/Globals/GMTotalPicturesProcessed.hpp" + +// masks for the handwritten neighbour-flag macro; MASM has no "|", so these must be literals +#define NEIGHBOUR_FLAGS_MASK_MARSH 0x20000000 // L_MARSH +#define NEIGHBOUR_FLAGS_MASK_SEA 0x1 // L_SEA +#define NEIGHBOUR_FLAGS_MASK_DEFAULT_EARTH 0x8000 // L_DEFAULT_EARTH_OR_TEXTURE +#define NEIGHBOUR_FLAGS_MASK_L2_SCRUB 0x1 // L2_SCRUB +#define NEIGHBOUR_FLAGS_MASK_L2_EARTH_AND_STONES 0x2 // L2_EARTH_AND_STONES +#define NEIGHBOUR_FLAGS_MASK_L2_PLATEAU_MEDIUM 0x4 // L2_PLATEAU_MEDIUM +#define NEIGHBOUR_FLAGS_MASK_L2_PLATEAU_HIGH 0x8 // L2_PLATEAU_HIGH +#define NEIGHBOUR_FLAGS_MASK_L2_OASIS_GRASS 0x10 // L2_OASIS_GRASS +#define NEIGHBOUR_FLAGS_MASK_L2_BEACH 0x20 // L2_BEACH +#define NEIGHBOUR_FLAGS_MASK_L2_STONES 0x40 // L2_STONES_OR_DRIVEN_SANDUnk + +#pragma optimize("", off) + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L2_BEACH; + using OpenSHC::Map::LogicHelpers::L2_EARTH_AND_STONES; + using OpenSHC::Map::LogicHelpers::L2_OASIS_GRASS; + using OpenSHC::Map::LogicHelpers::L2_PLATEAU_HIGH; + using OpenSHC::Map::LogicHelpers::L2_PLATEAU_MEDIUM; + using OpenSHC::Map::LogicHelpers::L2_SCRUB; + using OpenSHC::Map::LogicHelpers::L2_STONES_OR_DRIVEN_SANDUnk; + using OpenSHC::Map::LogicHelpers::L2_THICK_SCRUB; + using OpenSHC::Map::LogicHelpers::L_DEFAULT_EARTH_OR_TEXTURE; + using OpenSHC::Map::LogicHelpers::L_MARSH; + + // FUNCTION: STRONGHOLDCRUSADER 0x004FC9E0 + void TileMapState::updateGFXLayers() + { + /* + Contains the handwritten neighbour-flag macro nine times (see NeighbourFlagsAsm.hpp), which + is why the surrounding code is unoptimised: MSVC disables optimisation in a function holding + inline asm, so every field access reloads this from the frame. + + Two stores below are dead in this function but present in the original, because the body is + shared with updateMacroLayerRelated where they are read: "rotation" is reassigned from + MacroLayer at the end of the tile setup, and "height" is never read at all. + */ + /* + The locals are declared here, in this order, because the original was built without + optimisation: its stack slots are observable and MSVC assigns them per function, not per + scope. Declaring them at first use instead costs ~12 points of match (52.6% vs 64.5%). + */ + int rotation; + int blockColumn; + int gfxMode; + int index; + int macroHigh; + int blockRow; + int gfxBaseD; + int luminescence; + int gfxStride; + int subRow; + int subColumn; + int gfxBaseA; + int macroLow; + int gfxBaseE; + int height; + int gfxBaseB; + int gfxBaseC; + int macroMid; + int savedBitFlag; + + if (this->forceUpdateGFXLayers <= 0) { + return; + } + this->forceUpdateGFXLayers = this->forceUpdateGFXLayers - 1; + + if (MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::PathFindingState_Func::getYSmallerThanYLimit, DAT_PathFindingState::ptr)() + == FALSE) { + return; + } + + rotation = DAT_PathFindingState::instance.mappingYRelated % 10; + for (blockRow = this->someIndex; blockRow <= this->someLimit; blockRow++) { + for (blockColumn = this->someYLike; blockColumn <= this->someYLikeLimit; blockColumn++) { + if (DAT_TileMapState::instance.mapping40x40[blockRow][blockColumn] != 0) { + subRow = rotation; + rotation = 0; + for (; subRow < 10; subRow++) { + this->DAT_SomeY = blockRow * 10 + subRow; + this->DAT_SomeX = blockColumn * 10; + for (subColumn = 0; subColumn < 10; subColumn++, this->DAT_SomeX++) { + if (MACRO_CALL_MEMBER(OpenSHC::Rendering::ViewportRenderState_Func::xyAreValid, + DAT_ViewportRenderState::ptr)(this->DAT_SomeX, this->DAT_SomeY) + != FALSE) { + this->DAT_SomeTile + = MACRO_CALL_MEMBER(OpenSHC::Rendering::ViewportRenderState_Func::translateXYToTile, + DAT_ViewportRenderState::ptr)(this->DAT_SomeX, this->DAT_SomeY); + if ((this->LogicLayer[this->DAT_SomeTile] & L_DEFAULT_EARTH_OR_TEXTURE) != 0) { + if (this->GfxLayer[this->DAT_SomeTile] == 0) { + luminescence = this->LuminesenceLayer[this->DAT_SomeTile]; + if (luminescence < 2) { + luminescence = 2; + } + macroLow = (short)this->MacroLayer[this->DAT_SomeTile] & 0x3f; + macroMid = ((short)this->MacroLayer[this->DAT_SomeTile] & 0x7c0) >> 6; + macroHigh = ((short)this->MacroLayer[this->DAT_SomeTile] & 0xf000) >> 12; + macroHigh = macroHigh & 3; + rotation = (short)this->MacroLayer[this->DAT_SomeTile]; + this->PillarGFXLayer[this->DAT_SomeTile] + = (ushort)GMTotalPicturesProcessed::instance[9]; + + if ((this->LogicLayer[this->DAT_SomeTile] & L_MARSH) != 0) { + MACRO_NEIGHBOUR_FLAGS_LOGIC_4(1, NEIGHBOUR_FLAGS_MASK_MARSH) + gfxBaseA = 1; + gfxBaseB = 3; + gfxBaseC = 0x15; + gfxBaseD = 0x21; + gfxBaseE = 0x25; + gfxStride = 4; + gfxMode = 0; + } else if (((char)this->Logic2Layer[this->DAT_SomeTile] & L2_EARTH_AND_STONES) + != 0) { + height = this->HeightLayer[this->DAT_SomeTile]; + MACRO_NEIGHBOUR_FLAGS_TERRAIN_4(2, NEIGHBOUR_FLAGS_MASK_L2_EARTH_AND_STONES) + gfxBaseA = 0x99; + gfxBaseB = 0x9b; + gfxBaseC = 0xad; + gfxBaseD = 0xb9; + gfxBaseE = 0xbd; + gfxStride = 4; + gfxMode = 0; + } else if (((char)this->Logic2Layer[this->DAT_SomeTile] & L2_OASIS_GRASS) + != 0) { + MACRO_NEIGHBOUR_FLAGS_TERRAIN_4(3, NEIGHBOUR_FLAGS_MASK_L2_OASIS_GRASS) + gfxBaseA = 0x1c9; + gfxBaseB = 0x1cb; + gfxBaseC = 0x1dd; + gfxBaseD = 0x1e9; + gfxBaseE = 0x1ed; + gfxStride = 4; + gfxMode = 0; + } else if (((char)this->Logic2Layer[this->DAT_SomeTile] + & L2_STONES_OR_DRIVEN_SANDUnk) + != 0) { + MACRO_NEIGHBOUR_FLAGS_TERRAIN_4(4, NEIGHBOUR_FLAGS_MASK_L2_STONES) + gfxBaseA = 0x261; + gfxBaseB = 0x263; + gfxBaseC = 0x275; + gfxBaseD = 0x281; + gfxBaseE = 0x285; + gfxStride = 4; + gfxMode = 0; + } else if (((char)this->Logic2Layer[this->DAT_SomeTile] & L2_SCRUB) != 0) { + MACRO_NEIGHBOUR_FLAGS_TERRAIN_4(5, NEIGHBOUR_FLAGS_MASK_L2_SCRUB) + gfxBaseA = 0x2f9; + gfxBaseB = 0x2fb; + gfxBaseC = 0x30d; + gfxBaseD = 0x319; + gfxBaseE = 0x31d; + gfxStride = 4; + gfxMode = 0; + } else if (((char)this->Logic2Layer[this->DAT_SomeTile] & L2_THICK_SCRUB) + != 0) { + /* the original gathers L2_SCRUB here, not L2_THICK_SCRUB; kept as-is */ + MACRO_NEIGHBOUR_FLAGS_TERRAIN_4(6, NEIGHBOUR_FLAGS_MASK_L2_SCRUB) + gfxBaseA = 0x4a9; + gfxBaseB = 0x4ab; + gfxBaseC = 0x4bd; + gfxBaseD = 0x4c9; + gfxBaseE = 0x4cd; + gfxStride = 4; + gfxMode = 0; + } else if (((char)this->Logic2Layer[this->DAT_SomeTile] & L2_PLATEAU_MEDIUM) + != 0) { + MACRO_NEIGHBOUR_FLAGS_TERRAIN_4(7, NEIGHBOUR_FLAGS_MASK_L2_PLATEAU_MEDIUM) + gfxBaseA = 0x131; + gfxBaseB = 0x133; + gfxBaseC = 0x145; + gfxBaseD = 0x151; + gfxBaseE = 0x155; + gfxStride = 4; + gfxMode = 2; + } else if (((char)this->Logic2Layer[this->DAT_SomeTile] & L2_PLATEAU_HIGH) + != 0) { + MACRO_NEIGHBOUR_FLAGS_TERRAIN_4(8, NEIGHBOUR_FLAGS_MASK_L2_PLATEAU_HIGH) + gfxBaseA = 0x131; + gfxBaseB = 0x133; + gfxBaseC = 0x145; + gfxBaseD = 0x151; + gfxBaseE = 0x155; + gfxStride = 4; + gfxMode = 2; + } else if (((char)this->Logic2Layer[this->DAT_SomeTile] & L2_BEACH) != 0) { + MACRO_NEIGHBOUR_FLAGS_TERRAIN_4(9, NEIGHBOUR_FLAGS_MASK_L2_BEACH) + savedBitFlag = this->bitFlag; + MACRO_NEIGHBOUR_FLAGS_LOGIC_4(10, NEIGHBOUR_FLAGS_MASK_SEA) + this->bitFlag = this->bitFlag | savedBitFlag; + gfxBaseA = 0x391; + gfxBaseB = 0x393; + gfxBaseC = 0x3a5; + gfxBaseD = 0x3b1; + gfxBaseE = 0x3b5; + gfxStride = 4; + gfxMode = 0; + } else { + MACRO_NEIGHBOUR_FLAGS_LOGIC_4(11, NEIGHBOUR_FLAGS_MASK_DEFAULT_EARTH) + gfxBaseA = 0x131; + gfxBaseB = 0x133; + gfxBaseC = 0x145; + gfxBaseD = 0x151; + gfxBaseE = 0x155; + gfxStride = 4; + gfxMode = 2; + } + + if (macroLow == 1) { + this->bitFlag = ~this->bitFlag; + this->bitFlag = this->bitFlag & 0xaa; + if (this->mapOrientation == 0) { + this->bitFlag = MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::DirectionAlgorithmState_Func:: + rotateByteLeft, + DAT_DirectionAlgorithmState::ptr)(this->bitFlag, 0); + } else if (this->mapOrientation == 2) { + this->bitFlag = MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::DirectionAlgorithmState_Func:: + rotateByteLeft, + DAT_DirectionAlgorithmState::ptr)(this->bitFlag, 2); + } else if (this->mapOrientation == 4) { + this->bitFlag = MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::DirectionAlgorithmState_Func:: + rotateByteLeft, + DAT_DirectionAlgorithmState::ptr)(this->bitFlag, 4); + } else if (this->mapOrientation == 6) { + this->bitFlag = MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::DirectionAlgorithmState_Func:: + rotateByteLeft, + DAT_DirectionAlgorithmState::ptr)(this->bitFlag, 6); + } + + if (gfxMode == 1) { + this->GfxLayer[this->DAT_SomeTile] = 0; + for (index = 0; index < 4; index++) { + if (DAT_TerrainDefinedData::instance.field2165_0x1d54[index][0] + == this->bitFlag) { + this->GfxLayer[this->DAT_SomeTile] + = GMTotalPicturesProcessed::instance[55] + gfxBaseA + + (luminescence - 2) * gfxStride - 1 + + ((short)this->RandomLayer[this->DAT_SomeTile] & 1) + + DAT_TerrainDefinedData::instance + .field2165_0x1d54[index][1]; + } + } + for (index = 4; index < 8; index++) { + if (DAT_TerrainDefinedData::instance.field2165_0x1d54[index][0] + == this->bitFlag) { + this->GfxLayer[this->DAT_SomeTile] + = GMTotalPicturesProcessed::instance[55] + gfxBaseB + + (luminescence - 2) * gfxStride - 1 + + DAT_TerrainDefinedData::instance + .field2165_0x1d54[index][1]; + } + } + if (this->GfxLayer[this->DAT_SomeTile] == 0) { + this->GfxLayer[this->DAT_SomeTile] + = GMTotalPicturesProcessed::instance[55] + gfxBaseC + + (luminescence - 2) * gfxStride - 1 + + ((short)this->RandomLayer[this->DAT_SomeTile] & 3); + } + } else if (luminescence == 2) { + if (this->bitFlag != 0) { + this->GfxLayer[this->DAT_SomeTile] + = GMTotalPicturesProcessed::instance[55] + gfxBaseC + + ((short)this->RandomLayer[this->DAT_SomeTile] & 7) - 1; + } else { + this->GfxLayer[this->DAT_SomeTile] + = GMTotalPicturesProcessed::instance[55] + gfxBaseD + + ((short)this->RandomLayer[this->DAT_SomeTile] & 7) - 1; + } + } else if (gfxMode == 2) { + this->GfxLayer[this->DAT_SomeTile] + = GMTotalPicturesProcessed::instance[55] + gfxBaseA + + (luminescence - 3) * gfxStride - 1 + + ((short)this->RandomLayer[this->DAT_SomeTile] & 3); + } else if (this->bitFlag != 0) { + this->GfxLayer[this->DAT_SomeTile] + = GMTotalPicturesProcessed::instance[55] + gfxBaseA + + (luminescence - 3) * gfxStride - 1 + + ((short)this->RandomLayer[this->DAT_SomeTile] & 1); + } else { + this->GfxLayer[this->DAT_SomeTile] + = GMTotalPicturesProcessed::instance[55] + gfxBaseB + + (luminescence - 3) * gfxStride - 1 + + ((short)this->RandomLayer[this->DAT_SomeTile] & 1); + } + } else if (luminescence > 2) { + if (gfxMode == 0) { + this->GfxLayer[this->DAT_SomeTile] + = GMTotalPicturesProcessed::instance[55] + gfxBaseB + + (luminescence - 3) * gfxStride - 1 + + ((short)this->RandomLayer[this->DAT_SomeTile] & 1); + } else if (gfxMode == 2) { + this->GfxLayer[this->DAT_SomeTile] + = GMTotalPicturesProcessed::instance[55] + gfxBaseA + + (luminescence - 3) * gfxStride - 1 + + ((short)this->RandomLayer[this->DAT_SomeTile] & 3); + } else { + this->GfxLayer[this->DAT_SomeTile] + = GMTotalPicturesProcessed::instance[55] + gfxBaseD + + (luminescence - 2) * gfxStride - 1 + + ((short)this->RandomLayer[this->DAT_SomeTile] & 3); + } + } else if (macroLow == 2) { + if (gfxMode == 0) { + this->GfxLayer[this->DAT_SomeTile] + = GMTotalPicturesProcessed::instance[55] + gfxBaseD + + ((short)this->RandomLayer[this->DAT_SomeTile] & 7) - 1; + } else { + this->GfxLayer[this->DAT_SomeTile] + = GMTotalPicturesProcessed::instance[55] + gfxBaseD + + ((short)this->RandomLayer[this->DAT_SomeTile] & 3) - 1; + } + } else if (macroLow == 4) { + macroMid = DAT_TerrainDefinedData::instance + .field2162_0x1a54[this->mapOrientation / 2][macroMid]; + this->GfxLayer[this->DAT_SomeTile] = GMTotalPicturesProcessed::instance[55] + + gfxBaseE + macroMid + macroHigh * 4 - 1; + } else if (macroLow == 8) { + macroMid = DAT_TerrainDefinedData::instance + .field2163_0x1b54[this->mapOrientation / 2][macroMid]; + this->GfxLayer[this->DAT_SomeTile] = macroHigh * 9 + + (GMTotalPicturesProcessed::instance[55] + gfxBaseE + macroMid) + 0xf; + } else if (macroLow == 0x10) { + macroMid = DAT_TerrainDefinedData::instance + .field2164_0x1c54[this->mapOrientation / 2][macroMid]; + this->GfxLayer[this->DAT_SomeTile] = macroHigh * 16 + + (GMTotalPicturesProcessed::instance[55] + gfxBaseE + macroMid) + 0x33; + } + } + } + } + } + } + } + } + } + } +} +} + +#pragma optimize("", on) diff --git a/src/OpenSHC/Map/TileMapState/updateGameRelatedValue.cpp b/src/OpenSHC/Map/TileMapState/updateGameRelatedValue.cpp new file mode 100644 index 0000000000..33fa462f52 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/updateGameRelatedValue.cpp @@ -0,0 +1,37 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" + +#include "OpenSHC/Globals/DAT_GameState.hpp" +#include "OpenSHC/Globals/DAT_PathFindingState.hpp" + +namespace OpenSHC { +namespace Map { + + // FUNCTION: STRONGHOLDCRUSADER 0x00511850 + void TileMapState::updateGameRelatedValue() + { + if (DAT_GameState::instance.mapAndTime.gameEventRelatedCountdown == 0) { + return; + } + + if (DAT_GameState::instance.mapAndTime.gameEventRelatedCountdown == 0x28) { + this->field187_0x554a10 = -1; + } + DAT_GameState::instance.mapAndTime.gameEventRelatedCountdown + = DAT_GameState::instance.mapAndTime.gameEventRelatedCountdown - 1; + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::setSignpostDistanceForCampaignMission, this)(); + int signpostDistance = ((0x28 - DAT_GameState::instance.mapAndTime.gameEventRelatedCountdown) + * DAT_GameState::instance.mapAndTime.unk_signpostDistance) + / 0x28; + if (signpostDistance == this->field187_0x554a10) { + return; + } + + this->field187_0x554a10 = signpostDistance; + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::pathfindingUpdate_0x4a8ab0, + DAT_PathFindingState::ptr)(signpostDistance); + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/updateGfxLayer.cpp b/src/OpenSHC/Map/TileMapState/updateGfxLayer.cpp new file mode 100644 index 0000000000..7fc604047e --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/updateGfxLayer.cpp @@ -0,0 +1,2561 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Game/GameStateStructures.func.hpp" +#include "OpenSHC/Map/Navigation/DirectionAlgorithmState.func.hpp" +#include "OpenSHC/Rendering/ViewportRenderState.func.hpp" +#include "OpenSHC/Game/GameMode2.hpp" +#include "OpenSHC/Map/Buildings/BuildingType.hpp" +#include "OpenSHC/Map/TileMapState/NeighbourFlagsAsm.hpp" +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_DirectionAlgorithmState.hpp" +#include "OpenSHC/Globals/DAT_GameCore.hpp" +#include "OpenSHC/Globals/DAT_GameState.hpp" +#include "OpenSHC/Globals/DAT_GameSynchronyState.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_ViewportRenderState.hpp" +#include "OpenSHC/Globals/GMTotalPicturesProcessed.hpp" + +// masks for the handwritten neighbour-flag macro; MASM has no "|", so these must be literals +#define NEIGHBOUR_FLAGS_MASK_RIVER_OR_FORD 0x300000 // L_RIVER | L_FORD +#define NEIGHBOUR_FLAGS_MASK_WALL_OR_GATEHOUSE 0x100 // L_WALL_OR_GATEHOUSE + +/* the original was built without optimisation: frame pointer, locals off ebp, sub esp, 0x118 */ +#pragma optimize("", off) + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_BORDER; + using OpenSHC::Map::LogicHelpers::L_BORDER_EDGE; + using OpenSHC::Map::LogicHelpers::L_BOULDERS; + using OpenSHC::Map::LogicHelpers::L_BUILDING; + using OpenSHC::Map::LogicHelpers::L_DEFAULT_EARTH_OR_TEXTURE; + using OpenSHC::Map::LogicHelpers::L_FARM_FIELD_APPLE; + using OpenSHC::Map::LogicHelpers::L_FARM_FIELD_DAIRY; + using OpenSHC::Map::LogicHelpers::L_FARM_FIELD_HOP; + using OpenSHC::Map::LogicHelpers::L_FARM_FIELD_WHEAT; + using OpenSHC::Map::LogicHelpers::L_FORD; + using OpenSHC::Map::LogicHelpers::L_IRON; + using OpenSHC::Map::LogicHelpers::L_KEEP_NON_MANOR_HOUSE; + using OpenSHC::Map::LogicHelpers::L_MARSH; + using OpenSHC::Map::LogicHelpers::L_MOAT; + using OpenSHC::Map::LogicHelpers::L_OIL; + using OpenSHC::Map::LogicHelpers::L_PEBBLES; + using OpenSHC::Map::LogicHelpers::L_PLAIN2_AND_PITCH; + using OpenSHC::Map::LogicHelpers::L_RIVER; + using OpenSHC::Map::LogicHelpers::L_ROCKY; + using OpenSHC::Map::LogicHelpers::L_SEA; + using OpenSHC::Map::LogicHelpers::L_STAIRS; + using OpenSHC::Map::LogicHelpers::L_STOCKPILEUnk; + using OpenSHC::Map::LogicHelpers::L_WALL_OR_GATEHOUSE; + + using OpenSHC::Game::GameMode2; + using OpenSHC::Map::Buildings::BuildingType; + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x00509180 + void TileMapState::updateGfxLayer() + { + + OpenSHC::Map::Buildings::BuildingTypeShort BVar1; + ushort uVar2; + ushort uVar3; + short sVar4; + short sVar5; + byte bVar6; + byte bVar7; + int sVar8; + bool bVar10; + int bVar9; + BOOLEnum BVar11; + uint uVar12; + int iVar13; + int iVar14; + uint uVar15; + byte bVar16; + int iVar17; + uint* puVar18; + byte bVar19; + int local_d4; + uint local_c0; + int local_b8; + int local_b4; + short local_b0; + int local_ac; + int local_a4; + int local_a0; + short local_9c; + int local_94; + uint local_74; + int local_70; + int local_68; + int local_60; + int local_54; + uint local_48; + short local_44; + int local_38; + int local_30; + int local_24; + int local_18; + int local_14; + int local_10; + int local_c; + int local_8; + sVar8 = 0; + if (0 < this->forceUpdateTextureTilemap) { + this->forceUpdateTextureTilemap = this->forceUpdateTextureTilemap - 1; + local_c = DAT_PathFindingState::instance.mappingYRelated % 10; + for (local_18 = this->someIndex; local_18 <= this->someLimit; local_18 = local_18 + 1) { + for (local_10 = this->someYLike; local_10 <= this->someYLikeLimit; local_10 = local_10 + 1) { + if (*(char*)(local_18 * 0x28 + 0x1f93438 + local_10) != '\0') { + local_24 = local_c; + local_c = 0; + for (; local_24 < 10; local_24 = local_24 + 1) { + this->DAT_SomeY = local_18 * 10 + local_24; + this->DAT_SomeX = local_10 * 10; + for (local_30 = 0; local_30 < 10; local_30 = local_30 + 1) { + bVar9 = MACRO_CALL_MEMBER(OpenSHC::Rendering::ViewportRenderState_Func::xyAreValid, + DAT_ViewportRenderState::ptr)(this->DAT_SomeX, (uint)(this->DAT_SomeY)); + if ((bVar9 != 0) + && (this->DAT_SomeTile = MACRO_CALL_MEMBER( + OpenSHC::Rendering::ViewportRenderState_Func::translateXYToTile, + DAT_ViewportRenderState::ptr)(this->DAT_SomeX, this->DAT_SomeY), + (char)this->ChangedLayer[this->DAT_SomeTile] != 0)) { + if (this->BuildingLayer[this->DAT_SomeTile] == 0) { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::computeTileLuminescence, + this)(this->DAT_SomeTile, this->DAT_SomeY); + iVar17 = this->DAT_SomeX; + this->FloatingLayer[this->DAT_SomeTile] = 0; + this->MiscDisplayLayer[this->DAT_SomeTile] + = (short)this->MiscDisplayLayer[this->DAT_SomeTile] & 0xfc3f; + this->MiscDisplayLayer[this->DAT_SomeTile] + = (short)this->MiscDisplayLayer[this->DAT_SomeTile] & 0xf7ff; + if ((this->LogicLayer[this->DAT_SomeTile] & L_RIVER) == 0) { + if ((this->LogicLayer[this->DAT_SomeTile] & L_FORD) == 0) { + if ((this->LogicLayer[this->DAT_SomeTile] & L_FARM_FIELD_WHEAT) == 0) { + if ((this->LogicLayer[this->DAT_SomeTile] & L_FARM_FIELD_HOP) + == 0) { + if ((this->LogicLayer[this->DAT_SomeTile] & L_FARM_FIELD_APPLE + | L_FARM_FIELD_DAIRY) + == 0) { + if ((this->LogicLayer[this->DAT_SomeTile] + & L_WALL_OR_GATEHOUSE + | L_BUILDING | L_KEEP_NON_MANOR_HOUSE) + == 0 + && this->BuildingWasLayer[this->DAT_SomeTile] != '\0' + && ((short)this->MiscDisplayLayer[this->DAT_SomeTile] + & 0x10) + != 0) { + local_44 = 0; + switch (this->BuildingWasLayer[this->DAT_SomeTile]) { + case '\t': + case '\n': + case '\v': + case '\x18': + case '\x19': + case '$': + case '%': + case '&': + case '(': + case ')': + case '*': + case '+': + case ',': + case '-': + case '.': + case '0': + case '4': + case 'J': + case 'K': + case 'L': + case 'M': + case 'N': + case 'Z': + case 'j': + local_44 = 0xc; + } + if (((short)this->MiscDisplayLayer[this->DAT_SomeTile] + & 0x2000) + == 0) { + this->GfxLayer[this->DAT_SomeTile] + = (short) + GMTotalPicturesProcessed::instance[0x95] + + local_44 + 4 + + ((short)this->RandomLayer[this->DAT_SomeTile] + & 7); + } else { + this->GfxLayer[this->DAT_SomeTile] + = (short) + GMTotalPicturesProcessed::instance[0x95] + + local_44 + + ((short)this->RandomLayer[this->DAT_SomeTile] + & 7); + } + } else if ((this->LogicLayer[this->DAT_SomeTile] + & L_WALL_OR_GATEHOUSE) + == 0) { + if ((this->LogicLayer[this->DAT_SomeTile] & L_SEA + | L_ROCKY | L_WALL_OR_GATEHOUSE | L_BUILDING + | L_BOULDERS | L_PEBBLES | L_IRON | L_RIVER + | L_FARM_FIELD_WHEAT | L_FARM_FIELD_HOP + | L_FARM_FIELD_APPLE | L_FARM_FIELD_DAIRY + | L_KEEP_NON_MANOR_HOUSE | L_MARSH | L_OIL) + == 0) { + local_48 = 0; + this->WallOwnerLayer[this->DAT_SomeTile] + = this->WallOwnerLayer[this->DAT_SomeTile] + & 0xf7; + MACRO_NEIGHBOUR_FLAGS_LOGIC_8( + wall, NEIGHBOUR_FLAGS_MASK_WALL_OR_GATEHOUSE) + bVar19 = this->bitFlag; + MACRO_NEIGHBOUR_FLAGS_LOGIC_8(m1, 2) + bVar19 = ~this->bitFlag & bVar19; + if (bVar19 != 0) { + switch (bVar19 & 0xaa) { + case 10: + local_48 = 2; + if ((bVar19 & 0x15) == 0x15) { + local_48 = 0; + } + break; + case 0x28: + local_48 = (uint)((bVar19 & 0x54) != 0x54); + break; + case 0x82: + local_48 = 3; + if ((bVar19 & 0x45) == 0x45) { + local_48 = 0; + } + break; + case 0xa0: + local_48 = 4; + if ((bVar19 & 0x41) == 0x15) { + local_48 = 0; + } + } + if (local_48 != 0) { + MACRO_NEIGHBOUR_FLAGS_LOGIC_8(r1, 0x800) + if (this->bitFlag != 0) { + local_48 = 0; + } + } + if (local_48 != 0) { + /* the corner picks its two cardinal + neighbours and the diagonal between them + (the decompiler lost these four arms: + they are the jump table at 0x00510d94) */ + switch (local_48) { + case 1: + local_68 = this->DAT_SomeTile + + this->directionTranslationMatrix + [this->DAT_SomeY][2]; + local_60 = this->DAT_SomeTile + + this->directionTranslationMatrix + [this->DAT_SomeY][4]; + local_54 = this->DAT_SomeTile + + this->directionTranslationMatrix + [this->DAT_SomeY][3]; + break; + case 2: + local_68 = this->DAT_SomeTile + + this->directionTranslationMatrix + [this->DAT_SomeY][6]; + local_60 = this->DAT_SomeTile + + this->directionTranslationMatrix + [this->DAT_SomeY][4]; + local_54 = this->DAT_SomeTile + + this->directionTranslationMatrix + [this->DAT_SomeY][5]; + break; + case 3: + local_68 = this->DAT_SomeTile + + this->directionTranslationMatrix + [this->DAT_SomeY][6]; + local_60 = this->DAT_SomeTile + + this->directionTranslationMatrix + [this->DAT_SomeY][0]; + local_54 = this->DAT_SomeTile + + this->directionTranslationMatrix + [this->DAT_SomeY][7]; + break; + case 4: + local_68 = this->DAT_SomeTile + + this->directionTranslationMatrix + [this->DAT_SomeY][2]; + local_60 = this->DAT_SomeTile + + this->directionTranslationMatrix + [this->DAT_SomeY][0]; + local_54 = this->DAT_SomeTile + + this->directionTranslationMatrix + [this->DAT_SomeY][1]; + break; + } + bVar19 = this->HeightLayer[local_68]; + bVar16 = this->HeightLayer[local_60]; + bVar7 = this->HeightLayer[local_54]; + if ((this->LogicLayer[local_54] & 0x100U) + == 0) { + bVar7 = bVar16; + } + bVar6 = bVar16; + if (bVar19 < bVar16) { + bVar6 = bVar19; + } + if ((bVar6 < bVar7) + && (bVar7 = bVar16, bVar19 < bVar16)) { + bVar7 = bVar19; + } + if (this->HeightLayer[this->DAT_SomeTile] + < bVar7) { + this->WallGFXLayer[this->DAT_SomeTile] + = (ushort)bVar7; + if (DAT_TileMapState::instance + .DamageLayer[local_68] + != 0 + || DAT_TileMapState::instance + .DamageLayer[local_60] + != 0 + || (DAT_TileMapState::instance + .DamageLayer[local_54] + != 0 + && ((this->LogicLayer[local_54] + & 0x100U) + != 0))) { + this->WallOwnerLayer[this + ->DAT_SomeTile] + = this->WallOwnerLayer[this + ->DAT_SomeTile] + | 8; + } + } else { + local_48 = 0; + } + if (local_48 != 0) { + uVar12 = ((local_48 + 3) + - this->mapOrientation / 2) + % 4; + switch (uVar12) { + case 0: + this->MiscDisplayLayer[this + ->DAT_SomeTile] + = (short)this->MiscDisplayLayer + [this->DAT_SomeTile] + | 0x40; + this->AlphaGFXLayer[this + ->DAT_SomeTile] = 0x2f; + break; + case 1: + this->MiscDisplayLayer[this + ->DAT_SomeTile] + = (short)this->MiscDisplayLayer + [this->DAT_SomeTile] + | 0x200; + this->AlphaGFXLayer[this + ->DAT_SomeTile] = 0x2e; + break; + case 2: + this->MiscDisplayLayer[this + ->DAT_SomeTile] + = (short)this->MiscDisplayLayer + [this->DAT_SomeTile] + | 0x80; + this->AlphaGFXLayer[this + ->DAT_SomeTile] = 0x31; + break; + case 3: + this->MiscDisplayLayer[this + ->DAT_SomeTile] + = (short)this->MiscDisplayLayer + [this->DAT_SomeTile] + | 0x100; + this->AlphaGFXLayer[this + ->DAT_SomeTile] = 0x30; + } + } + } + } + } + } else { + this->wallCornerRotation = MACRO_CALL_MEMBER( + OpenSHC::Map::TileMapState_Func:: + computeWallCornerRenderRotation, + this)(iVar17); + this->WallGFXLayer[this->DAT_SomeTile] + = (short)GMTotalPicturesProcessed::instance[10] - 1 + + (short)this->wallCornerRotation; + sVar4 = (short)GMTotalPicturesProcessed::instance[0xc]; + if ((char)this->DamageLayer[this->DAT_SomeTile] == 0) { + if ((this->LogicLayer[this->DAT_SomeTile] & 0x200U) + == 0) { + if ((this->LogicLayer[this->DAT_SomeTile] + & 0x800U) + == 0) { + if (this->LuminesenceLayer[this + ->DAT_SomeTile] + < 4) { + this->GfxLayer[this->DAT_SomeTile] + = sVar4 + 0x60 + + ((short)this->RandomLayer[this + ->DAT_SomeTile] + & 7); + } else { + this->GfxLayer[this->DAT_SomeTile] + = sVar4 + 0x68 + + ((short)this->RandomLayer[this + ->DAT_SomeTile] + & 7); + } + } else { + BVar11 = MACRO_CALL_MEMBER( + OpenSHC::Map::TileMapState_Func:: + hasHigherNeighborWithStairs, + this)( + this->DAT_SomeTile, this->DAT_SomeY, 0); + if (BVar11 == FALSE) { + BVar11 = MACRO_CALL_MEMBER( + OpenSHC::Map::TileMapState_Func:: + hasHigherNeighborWithStairs, + this)(this->DAT_SomeTile, + this->DAT_SomeY, 2); + if (BVar11 == FALSE) { + BVar11 = MACRO_CALL_MEMBER( + OpenSHC::Map::TileMapState_Func:: + hasHigherNeighborWithStairs, + this)(this->DAT_SomeTile, + this->DAT_SomeY, 4); + if (BVar11 == FALSE) { + BVar11 = MACRO_CALL_MEMBER( + OpenSHC::Map::TileMapState_Func:: + hasHigherNeighborWithStairs, + this)(this->DAT_SomeTile, + this->DAT_SomeY, 6); + if (BVar11 == FALSE) { + BVar11 = MACRO_CALL_MEMBER( + OpenSHC::Map:: + TileMapState_Func:: + hasHigherPlainNeighborWithWallOrGatehouse, + this)( + this->DAT_SomeTile, + this->DAT_SomeY, 0); + if (BVar11 == FALSE) { + BVar11 = MACRO_CALL_MEMBER( + OpenSHC::Map:: + TileMapState_Func:: + hasHigherPlainNeighborWithWallOrGatehouse, + this)( + this->DAT_SomeTile, + this->DAT_SomeY, 2); + if (BVar11 == FALSE) { + BVar11 = MACRO_CALL_MEMBER( + OpenSHC::Map:: + TileMapState_Func:: + hasHigherPlainNeighborWithWallOrGatehouse, + this)( + this->DAT_SomeTile, + this->DAT_SomeY, + 4); + if (BVar11 + == FALSE) { + BVar11 = MACRO_CALL_MEMBER( + OpenSHC::Map:: + TileMapState_Func:: + hasHigherPlainNeighborWithWallOrGatehouse, + this)( + this->DAT_SomeTile, + this->DAT_SomeY, + 6); + if (BVar11 + == FALSE) { + this->GfxLayer + [this->DAT_SomeTile] + = (short)GMTotalPicturesProcessed:: + instance + [0xc] + + 0x68; + } else { + this->GfxLayer + [this->DAT_SomeTile] + = (short)GMTotalPicturesProcessed:: + instance + [0xc] + + 0x85; + } + } else { + this->GfxLayer + [this->DAT_SomeTile] + = (short)GMTotalPicturesProcessed:: + instance + [0xc] + + 0x88; + } + } else { + this->GfxLayer[this + ->DAT_SomeTile] + = (short)GMTotalPicturesProcessed:: + instance + [0xc] + + 0x87; + } + } else { + this->GfxLayer[this + ->DAT_SomeTile] + = (short) + GMTotalPicturesProcessed:: + instance + [0xc] + + 0x86; + } + } else { + this->GfxLayer[this + ->DAT_SomeTile] + = (short) + GMTotalPicturesProcessed:: + instance[0xc] + + 0x85; + } + } else { + this->GfxLayer[this + ->DAT_SomeTile] + = (short) + GMTotalPicturesProcessed:: + instance[0xc] + + 0x88; + } + } else { + this->GfxLayer[this->DAT_SomeTile] + = (short) + GMTotalPicturesProcessed:: + instance[0xc] + + 0x87; + } + } else { + this->GfxLayer[this->DAT_SomeTile] + = (short)GMTotalPicturesProcessed:: + instance[0xc] + + 0x86; + } + } + } else { + BVar11 = MACRO_CALL_MEMBER( + OpenSHC::Map::TileMapState_Func:: + isWallCornerForCardinalDirection, + this)( + this->DAT_SomeTile, this->DAT_SomeY, 0); + if (BVar11 == FALSE) { + BVar11 = MACRO_CALL_MEMBER( + OpenSHC::Map::TileMapState_Func:: + isWallCornerForCardinalDirection, + this)( + this->DAT_SomeTile, this->DAT_SomeY, 2); + if (BVar11 == FALSE) { + uVar12 = MACRO_CALL_MEMBER( + OpenSHC::Map::TileMapState_Func:: + isWallCornerForDiagonalDirection, + this)(this->DAT_SomeTile, + this->DAT_SomeY, 1); + if (uVar12 == 0) { + uVar12 = MACRO_CALL_MEMBER( + OpenSHC::Map::TileMapState_Func:: + isWallCornerForDiagonalDirection, + this)(this->DAT_SomeTile, + this->DAT_SomeY, 3); + if (uVar12 == 0) { + uVar12 = MACRO_CALL_MEMBER( + OpenSHC::Map::TileMapState_Func:: + isWallCornerForDiagonalDirection, + this)(this->DAT_SomeTile, + this->DAT_SomeY, 5); + if (uVar12 == 0) { + uVar12 = MACRO_CALL_MEMBER( + OpenSHC::Map:: + TileMapState_Func:: + isWallCornerForDiagonalDirection, + this)( + this->DAT_SomeTile, + this->DAT_SomeY, 7); + sVar4 = (short) + GMTotalPicturesProcessed:: + instance[0xc]; + if (uVar12 == 0) { + this->GfxLayer[this + ->DAT_SomeTile] + = sVar4 + 0x84; + this->LogicLayer[this + ->DAT_SomeTile] + = this->LogicLayer + [this->DAT_SomeTile] + | 0x400000; + } else { + if (this->mapOrientation + == 0) { + this->GfxLayer[this + ->DAT_SomeTile] + = sVar4 + 0x81; + } else if ( + this->mapOrientation + == 2) { + this->GfxLayer[this + ->DAT_SomeTile] + = sVar4 + 0x80; + } else if ( + this->mapOrientation + == 4) { + this->GfxLayer[this + ->DAT_SomeTile] + = sVar4 + 0x83; + } else if ( + this->mapOrientation + == 6) { + this->GfxLayer[this + ->DAT_SomeTile] + = sVar4 + 0x82; + } + this->LogicLayer[this + ->DAT_SomeTile] + = this->LogicLayer + [this->DAT_SomeTile] + | 0x400000; + } + } else { + sVar4 = (short) + GMTotalPicturesProcessed:: + instance[0xc]; + if (this->mapOrientation + == 0) { + this->GfxLayer[this + ->DAT_SomeTile] + = sVar4 + 0x80; + } else if ( + this->mapOrientation + == 2) { + this->GfxLayer[this + ->DAT_SomeTile] + = sVar4 + 0x83; + } else if ( + this->mapOrientation + == 4) { + this->GfxLayer[this + ->DAT_SomeTile] + = sVar4 + 0x82; + } else if ( + this->mapOrientation + == 6) { + this->GfxLayer[this + ->DAT_SomeTile] + = sVar4 + 0x81; + } + this->LogicLayer[this + ->DAT_SomeTile] + = this->LogicLayer[this + ->DAT_SomeTile] + | 0x400000; + } + } else { + sVar4 = (short) + GMTotalPicturesProcessed:: + instance[0xc]; + if (this->mapOrientation == 0) { + this->GfxLayer[this + ->DAT_SomeTile] + = sVar4 + 0x83; + } else if (this->mapOrientation + == 2) { + this->GfxLayer[this + ->DAT_SomeTile] + = sVar4 + 0x82; + } else if (this->mapOrientation + == 4) { + this->GfxLayer[this + ->DAT_SomeTile] + = sVar4 + 0x81; + } else if (this->mapOrientation + == 6) { + this->GfxLayer[this + ->DAT_SomeTile] + = sVar4 + 0x80; + } + this->LogicLayer[this + ->DAT_SomeTile] + = this->LogicLayer[this + ->DAT_SomeTile] + | 0x400000; + } + } else { + sVar4 = (short) + GMTotalPicturesProcessed:: + instance[0xc]; + if (this->mapOrientation == 0) { + this->GfxLayer[this + ->DAT_SomeTile] + = sVar4 + 0x82; + } else if (this->mapOrientation + == 2) { + this->GfxLayer[this + ->DAT_SomeTile] + = sVar4 + 0x81; + } else if (this->mapOrientation + == 4) { + this->GfxLayer[this + ->DAT_SomeTile] + = sVar4 + 0x80; + } else if (this->mapOrientation + == 6) { + this->GfxLayer[this + ->DAT_SomeTile] + = sVar4 + 0x83; + } + this->LogicLayer[this->DAT_SomeTile] + = this->LogicLayer[this + ->DAT_SomeTile] + | 0x400000; + } + } else { + sVar4 + = (short)GMTotalPicturesProcessed:: + instance[0xc]; + if ((this->mapOrientation == 0) + || (this->mapOrientation == 4)) { + if ((this->LogicLayer[this + ->DAT_SomeTile] + & 0x400000U) + == 0) { + this->GfxLayer[this + ->DAT_SomeTile] = sVar4 + + 0x70 + + ((short)this->RandomLayer + [this->DAT_SomeTile] + & 3); + } else { + this->GfxLayer[this + ->DAT_SomeTile] = sVar4 + + 0x78 + + ((short)this->RandomLayer + [this->DAT_SomeTile] + & 3); + } + } else if ((this->LogicLayer[this + ->DAT_SomeTile] + & 0x400000U) + == 0) { + this->GfxLayer[this->DAT_SomeTile] + = sVar4 + 0x74 + + ((short)this->RandomLayer[this + ->DAT_SomeTile] + & 3); + } else { + this->GfxLayer[this->DAT_SomeTile] + = sVar4 + 0x7c + + ((short)this->RandomLayer[this + ->DAT_SomeTile] + & 3); + } + } + } else { + sVar4 = (short) + GMTotalPicturesProcessed::instance[0xc]; + if ((this->mapOrientation == 0) + || (this->mapOrientation == 4)) { + if ((this->LogicLayer[this + ->DAT_SomeTile] + & 0x400000U) + == 0) { + this->GfxLayer[this->DAT_SomeTile] + = sVar4 + 0x74 + + ((short)this->RandomLayer[this + ->DAT_SomeTile] + & 3); + } else { + this->GfxLayer[this->DAT_SomeTile] + = sVar4 + 0x7c + + ((short)this->RandomLayer[this + ->DAT_SomeTile] + & 3); + } + } else if ((this->LogicLayer[this + ->DAT_SomeTile] + & 0x400000U) + == 0) { + this->GfxLayer[this->DAT_SomeTile] + = sVar4 + 0x70 + + ((short)this->RandomLayer[this + ->DAT_SomeTile] + & 3); + } else { + this->GfxLayer[this->DAT_SomeTile] + = sVar4 + 0x78 + + ((short)this->RandomLayer[this + ->DAT_SomeTile] + & 3); + } + } + } + } else { + this->GfxLayer[this->DAT_SomeTile] = sVar4 + 0x8a + + ((short)this->RandomLayer[this->DAT_SomeTile] + & 7); + } + } + } + } else { + MACRO_CALL_MEMBER( + OpenSHC::Map::TileMapState_Func::computeClimbRampRotation, + this)(this->DAT_SomeTile, (uint)(iVar17), + (uint)(this->DAT_SomeY)); + this->PillarGFXLayer[this->DAT_SomeTile] + = (short)GMTotalPicturesProcessed::instance[9] - 1 + + (short)this->wallCornerRotation; + this->MiscDisplayLayer[this->DAT_SomeTile] + = (short)this->MiscDisplayLayer[this->DAT_SomeTile] | 0x800; + this->GfxLayer[this->DAT_SomeTile] + = (short)GMTotalPicturesProcessed::instance[0xe] + 0x25 + + ((short)this->RandomLayer[this->DAT_SomeTile] & 1) * 9; + DAT_BuildingsState::instance.field14_0x18e024 = 1; + } + } else { + MACRO_CALL_MEMBER( + OpenSHC::Map::TileMapState_Func::computeClimbRampRotation, + this)( + this->DAT_SomeTile, (uint)(iVar17), (uint)(this->DAT_SomeY)); + this->PillarGFXLayer[this->DAT_SomeTile] + = (short)GMTotalPicturesProcessed::instance[9] - 1 + + (short)this->wallCornerRotation; + this->MiscDisplayLayer[this->DAT_SomeTile] + = (short)this->MiscDisplayLayer[this->DAT_SomeTile] | 0x800; + this->GfxLayer[this->DAT_SomeTile] + = ((short)this->RandomLayer[this->DAT_SomeTile] & 3) + + (short)GMTotalPicturesProcessed::instance[0xe]; + DAT_BuildingsState::instance.field14_0x18e024 = 1; + } + } else { + BVar11 = MACRO_CALL_MEMBER( + OpenSHC::Map::TileMapState_Func::isTileSuitableForBrushPlacement, + this)(this->DAT_SomeTile, (uint)(iVar17), (uint)(this->DAT_SomeY)); + if (BVar11 == FALSE) { + this->PillarGFXLayer[this->DAT_SomeTile] = 0x20; + } else { + this->PillarGFXLayer[this->DAT_SomeTile] + = ((short)this->RandomLayer[this->DAT_SomeTile] & 0xf) + 0x23; + } + this->GfxLayer[this->DAT_SomeTile] + = (short)GMTotalPicturesProcessed::instance[5] + 0x29c; + } + } else { + BVar11 = MACRO_CALL_MEMBER( + OpenSHC::Map::TileMapState_Func::isTileSuitableForBrushPlacement, this)( + this->DAT_SomeTile, (uint)(iVar17), (uint)(this->DAT_SomeY)); + if (BVar11 == FALSE) { + this->PillarGFXLayer[this->DAT_SomeTile] = 0x20; + } else { + this->PillarGFXLayer[this->DAT_SomeTile] + = ((short)this->RandomLayer[this->DAT_SomeTile] & 0xf) + 0x23; + } + this->GfxLayer[this->DAT_SomeTile] + = (short)GMTotalPicturesProcessed::instance[5] + 0x214; + } + } else if (DAT_BuildingsState::instance + .buildings[this->BuildingLayer[this->DAT_SomeTile]] + .buildingType + == OpenSHC::Map::Buildings::BT_DRAWBRIDGE) { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::computeTileLuminescence, + this)(this->DAT_SomeTile, this->DAT_SomeY); + } + } + this->DAT_SomeX = this->DAT_SomeX + 1; + } + } + } + } + } + local_c = DAT_PathFindingState::instance.mappingYRelated % 10; + for (local_18 = this->someIndex; local_18 <= this->someLimit; local_18 = local_18 + 1) { + for (local_10 = this->someYLike; local_10 <= this->someYLikeLimit; local_10 = local_10 + 1) { + if (*(char*)(local_18 * 0x28 + 0x1f93438 + local_10) != '\0') { + local_24 = local_c; + local_c = 0; + for (; local_24 < 10; local_24 = local_24 + 1) { + this->DAT_SomeY = local_18 * 10 + local_24; + this->DAT_SomeX = local_10 * 10; + for (local_30 = 0; local_30 < 10; local_30 = local_30 + 1) { + BVar11 = MACRO_CALL_MEMBER(OpenSHC::Rendering::ViewportRenderState_Func::xyAreValid, + DAT_ViewportRenderState::ptr)(this->DAT_SomeX, (uint)(this->DAT_SomeY)); + if (BVar11 != FALSE + && (this->DAT_SomeTile = MACRO_CALL_MEMBER( + OpenSHC::Rendering::ViewportRenderState_Func::translateXYToTile, + DAT_ViewportRenderState::ptr)(this->DAT_SomeX, this->DAT_SomeY), + (this->LogicLayer[this->DAT_SomeTile] & 0x100201U) != 0) + && (char)this->ChangedLayer[this->DAT_SomeTile] != 0 + && this->BuildingLayer[this->DAT_SomeTile] == 0 + && (this->LogicLayer[this->DAT_SomeTile] & 0x10000030U) == 0) { + if ((this->LogicLayer[this->DAT_SomeTile] & 1U) == 0) { + if ((this->LogicLayer[this->DAT_SomeTile] & 0x100000U) != 0) { + MACRO_CALL_MEMBER( + OpenSHC::Map::TileMapState_Func::computeTileCliffEdgeFlags, this)( + this->DAT_SomeTile, this->DAT_SomeX, this->DAT_SomeY); + } + } else { + this->MiscDisplayLayer[this->DAT_SomeTile] + = (short)this->MiscDisplayLayer[this->DAT_SomeTile] & 0xfffc; + iVar17 = this->DAT_SomeTile + + this->directionTranslationMatrix[this->DAT_SomeY][this->mapOrientation]; + this->gfxTileHeight = (ushort)this->HeightLayer[iVar17]; + if ((this->LogicLayer[iVar17] & 1U) != 0) { + this->gfxTileHeight = 0; + } + if ((this->LogicLayer[iVar17] & 0x80U) != 0) { + this->gfxTileHeight = 0x14; + } + if (0x13 < (short)this->gfxTileHeight) { + sVar4 = (short)GMTotalPicturesProcessed::instance[0xa6]; + if ((short)this->gfxTileHeight < 0x5b) { + if ((short)this->gfxTileHeight < 0x29) { + this->GfxLayer[this->DAT_SomeTile] = sVar4 + 0x5dc; + } else { + this->GfxLayer[this->DAT_SomeTile] = sVar4 + 0x5e2; + } + } else { + this->GfxLayer[this->DAT_SomeTile] = sVar4 + 0x5ee; + } + this->PillarGFXLayer[this->DAT_SomeTile] + = (ushort)GMTotalPicturesProcessed::instance[9]; + this->MiscDisplayLayer[this->DAT_SomeTile] + = (short)this->MiscDisplayLayer[this->DAT_SomeTile] | 0x40; + } + local_74 = 0; + this->bitFlag = 0; + for (local_70 = 0; local_70 < 8; local_70 = local_70 + 1) { + iVar17 = this->DAT_SomeTile + + this->directionTranslationMatrix[this->DAT_SomeY][local_70]; + if (this->HeightLayer[iVar17] < 0x14) { + if ((this->LogicLayer[iVar17] & 0x100031U) == 0) { + this->bitFlag + = this->bitFlag | (byte)(0x80 >> ((byte)local_70 & 0x1f)); + } + if ((this->LogicLayer[iVar17] & 0x100001U) == 0 + && ((char)this->Logic2Layer[iVar17] & 0x20) != 0) { + local_74 = 0x80 >> ((byte)local_70 & 0x1f) | local_74; + } + } + } + if (this->bitFlag != 0) { + this->MiscDisplayLayer[this->DAT_SomeTile] + = (short)this->MiscDisplayLayer[this->DAT_SomeTile] | 0x100; + this->CertainPathLayer[this->DAT_SomeTile] + = (ushort)this->bitFlag | (ushort)(local_74 << 8); + } + } + if ((this->LogicLayer[this->DAT_SomeTile] & 0x200U) != 0) { + uVar12 = (this->screenSouthEastDirection + 7) % 8; + iVar17 = this->DAT_SomeTile + + this->directionTranslationMatrix[this->DAT_SomeY][uVar12]; + uVar12 = (this->screenSouthEastDirection + 1) % 8; + iVar13 = this->DAT_SomeTile + + this->directionTranslationMatrix[this->DAT_SomeY][uVar12]; + if (((this->LogicLayer[iVar17] | this->LogicLayer[iVar13]) & 1U) == 0 + && ((short)this->MiscDisplayLayer[iVar17] & 0x3c0) != 0 + && ((short)this->MiscDisplayLayer[iVar13] & 0x3c0) != 0) { + if (this->LuminesenceLayer[this->DAT_SomeTile] < 4) { + this->GfxLayer[this->DAT_SomeTile] + = (short)GMTotalPicturesProcessed::instance[0xc] + 0x60 + + ((short)this->RandomLayer[this->DAT_SomeTile] & 7); + } else { + this->GfxLayer[this->DAT_SomeTile] + = (short)GMTotalPicturesProcessed::instance[0xc] + 0x68 + + ((short)this->RandomLayer[this->DAT_SomeTile] & 7); + } + } + uVar12 = (this->screenSouthEastDirection + 1) % 8; + iVar17 = this->DAT_SomeTile + + this->directionTranslationMatrix[this->DAT_SomeY][uVar12]; + uVar12 = (this->screenSouthEastDirection + 3) % 8; + iVar13 = this->DAT_SomeTile + + this->directionTranslationMatrix[this->DAT_SomeY][uVar12]; + if (((this->LogicLayer[iVar17] | this->LogicLayer[iVar13]) & 1U) == 0 + && ((short)this->MiscDisplayLayer[iVar17] & 0x3c0) != 0 + && ((short)this->MiscDisplayLayer[iVar13] & 0x3c0) != 0) { + if ((this->DAT_SomeY & 1U) == 0) { + this->GfxLayer[this->DAT_SomeTile] + = (short)GMTotalPicturesProcessed::instance[0xc] + 0x138; + } else { + this->GfxLayer[this->DAT_SomeTile] + = (short)GMTotalPicturesProcessed::instance[0xc] + 0x137; + } + this->MiscDisplayLayer[this->DAT_SomeTile] + = (short)this->MiscDisplayLayer[this->DAT_SomeTile] | 0x3c0; + } + uVar12 = (this->screenSouthEastDirection + 5) % 8; + iVar17 = this->DAT_SomeTile + + this->directionTranslationMatrix[this->DAT_SomeY][uVar12]; + uVar12 = (this->screenSouthEastDirection + 7) % 8; + iVar13 = this->DAT_SomeTile + + this->directionTranslationMatrix[this->DAT_SomeY][uVar12]; + if (((this->LogicLayer[iVar17] | this->LogicLayer[iVar13]) & 1U) == 0 + && ((short)this->MiscDisplayLayer[iVar17] & 0x3c0) != 0 + && ((short)this->MiscDisplayLayer[iVar13] & 0x3c0) != 0) { + if ((this->DAT_SomeY & 1U) == 0) { + this->GfxLayer[this->DAT_SomeTile] + = (short)GMTotalPicturesProcessed::instance[0xc] + 0x13a; + } else { + this->GfxLayer[this->DAT_SomeTile] + = (short)GMTotalPicturesProcessed::instance[0xc] + 0x139; + } + this->MiscDisplayLayer[this->DAT_SomeTile] + = (short)this->MiscDisplayLayer[this->DAT_SomeTile] | 0x3c0; + } + uVar12 = (this->screenSouthEastDirection + 3) % 8; + iVar17 = this->DAT_SomeTile + + this->directionTranslationMatrix[this->DAT_SomeY][uVar12]; + uVar12 = (this->screenSouthEastDirection + 5) % 8; + iVar13 = this->DAT_SomeTile + + this->directionTranslationMatrix[this->DAT_SomeY][uVar12]; + if (((this->LogicLayer[iVar17] | this->LogicLayer[iVar13]) & 1U) == 0 + && ((short)this->MiscDisplayLayer[iVar17] & 0x3c0) != 0 + && ((short)this->MiscDisplayLayer[iVar13] & 0x3c0) != 0) { + uVar12 = (int)this->DAT_SomeY % 8; + this->GfxLayer[this->DAT_SomeTile] + = (short)GMTotalPicturesProcessed::instance[0xc] + 0x12f + + (short)uVar12; + this->MiscDisplayLayer[this->DAT_SomeTile] + = (short)this->MiscDisplayLayer[this->DAT_SomeTile] | 0x3c0; + } + } + } + this->DAT_SomeX = this->DAT_SomeX + 1; + } + } + } + } + } + local_c = DAT_PathFindingState::instance.mappingYRelated % 10; + for (local_18 = this->someIndex; local_18 <= this->someLimit; local_18 = local_18 + 1) { + for (local_10 = this->someYLike; local_10 <= this->someYLikeLimit; local_10 = local_10 + 1) { + if (*(char*)(local_18 * 0x28 + 0x1f93438 + local_10) != '\0') { + local_24 = local_c; + local_c = 0; + for (; local_24 < 10; local_24 = local_24 + 1) { + this->DAT_SomeY = local_18 * 10 + local_24; + this->DAT_SomeX = local_10 * 10; + for (local_30 = 0; local_30 < 10; local_30 = local_30 + 1) { + BVar11 = MACRO_CALL_MEMBER(OpenSHC::Rendering::ViewportRenderState_Func::xyAreValid, + DAT_ViewportRenderState::ptr)(this->DAT_SomeX, (uint)(this->DAT_SomeY)); + if (BVar11 != FALSE + && (this->DAT_SomeTile = MACRO_CALL_MEMBER( + OpenSHC::Rendering::ViewportRenderState_Func::translateXYToTile, + DAT_ViewportRenderState::ptr)(this->DAT_SomeX, this->DAT_SomeY), + (this->LogicLayer[this->DAT_SomeTile] & 1U) != 0) + && (char)this->ChangedLayer[this->DAT_SomeTile] != 0 + && (this->LogicLayer[this->DAT_SomeTile] & 0x10000030U) == 0 + && this->BuildingLayer[this->DAT_SomeTile] == 0 + && ((short)this->MiscDisplayLayer[this->DAT_SomeTile] & 0x40) == 0) { + MACRO_NEIGHBOUR_FLAGS_MISC_8(m2, 0x80) + bVar19 = this->bitFlag; + MACRO_NEIGHBOUR_FLAGS_MISC_8(m3, 0x40) + bVar16 = this->bitFlag; + this->bitFlag = bVar16 & ~bVar19; + if (this->bitFlag != 0) { + this->GfxLayer[this->DAT_SomeTile] + = (short)GMTotalPicturesProcessed::instance[0xa6] + 0x5d0; + this->PillarGFXLayer[this->DAT_SomeTile] + = (ushort)GMTotalPicturesProcessed::instance[9]; + this->MiscDisplayLayer[this->DAT_SomeTile] + = (short)this->MiscDisplayLayer[this->DAT_SomeTile] | 0x80; + } + } + this->DAT_SomeX = this->DAT_SomeX + 1; + } + } + } + } + } + local_c = DAT_PathFindingState::instance.mappingYRelated % 10; + for (local_18 = this->someIndex; local_18 <= this->someLimit; local_18 = local_18 + 1) { + for (local_10 = this->someYLike; local_10 <= this->someYLikeLimit; local_10 = local_10 + 1) { + if (*(char*)(local_18 * 0x28 + 0x1f93438 + local_10) != '\0') { + local_24 = local_c; + local_c = 0; + for (; local_24 < 10; local_24 = local_24 + 1) { + this->DAT_SomeY = local_18 * 10 + local_24; + this->DAT_SomeX = local_10 * 10; + for (local_30 = 0; local_30 < 10; local_30 = local_30 + 1) { + BVar11 = MACRO_CALL_MEMBER(OpenSHC::Rendering::ViewportRenderState_Func::xyAreValid, + DAT_ViewportRenderState::ptr)(this->DAT_SomeX, (uint)(this->DAT_SomeY)); + if (BVar11 != FALSE + && (this->DAT_SomeTile = MACRO_CALL_MEMBER( + OpenSHC::Rendering::ViewportRenderState_Func::translateXYToTile, + DAT_ViewportRenderState::ptr)(this->DAT_SomeX, this->DAT_SomeY), + (this->LogicLayer[this->DAT_SomeTile] & L_BORDER | L_BORDER_EDGE) == 0) + && (char)this->ChangedLayer[this->DAT_SomeTile] != 0) { + this->ChangedLayer[this->DAT_SomeTile] + = (char)this->ChangedLayer[this->DAT_SomeTile] - 1; + iVar17 = this->DAT_SomeX; + if ((this->LogicLayer[this->DAT_SomeTile] & L_SEA) == 0) { + if ((this->LogicLayer[this->DAT_SomeTile] & L_RIVER) == 0) { + if ((this->LogicLayer[this->DAT_SomeTile] & L_FORD) == 0) { + if ((this->LogicLayer[this->DAT_SomeTile] & L_PLAIN2_AND_PITCH) == 0) { + if (this->BuildingLayer[this->DAT_SomeTile] != 0) { + iVar13 = (int)this->BuildingLayer[this->DAT_SomeTile]; + if (DAT_BuildingsState::instance.buildings[iVar13].buildingType + == OpenSHC::Map::Buildings::BT_STOCKPILE) { + this->wallCornerRotation + = MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func:: + computeWallCornerRenderRotation, + this)(this->DAT_SomeX); + this->WallGFXLayer[this->DAT_SomeTile] + = (short)GMTotalPicturesProcessed::instance[10] - 1 + + (short)this->wallCornerRotation; + } + iVar14 = MACRO_CALL_MEMBER( + OpenSHC::Map::TileMapState_Func::computeClimbRampRotation, + this)(this->DAT_SomeTile, (uint)(iVar17), + (uint)(this->DAT_SomeY)); + BVar1 = DAT_BuildingsState::instance.buildings[iVar13] + .buildingType; + if (((BVar1 == OpenSHC::Map::Buildings::BT_FIREBALLISTA) + || ((0x4f < (short)BVar1 && ((short)BVar1 < 0x55)))) + && iVar14 == 0) { + this->PillarGFXLayer[this->DAT_SomeTile] + = (short)(((((int)(uint)this + ->HeightLayer[this->DAT_SomeTile] + >> 3) + - 1) + * 0x40) + / 2) + + (short)GMTotalPicturesProcessed::instance[3] + + (ushort)this->LuminesenceLayer[this->DAT_SomeTile] * 4 + + ((short)this->RandomLayer[this->DAT_SomeTile] & 3); + } else { + this->PillarGFXLayer[this->DAT_SomeTile] + = (short)GMTotalPicturesProcessed::instance[9] - 1 + + (short)this->wallCornerRotation; + this->MiscDisplayLayer[this->DAT_SomeTile] + = (short)this->MiscDisplayLayer[this->DAT_SomeTile] + | 0x800; + } + if (DAT_BuildingsState::instance.buildings[iVar13].buildingType + == OpenSHC::Map::Buildings::BT_KILLINGPIT + && DAT_BuildingsState::instance.buildings[iVar13].state < 1 + && (BVar11 = MACRO_CALL_MEMBER( + OpenSHC::Game::GameStateStructures_Func::isSameTeam, + DAT_GameState::ptr)( + (int)DAT_BuildingsState::instance.buildings[iVar13] + .owner, + (int)(DAT_GameSynchronyState::instance + .currentPlayerSlotID)), + BVar11 == FALSE + && (DAT_GameCore::instance.gameMode_2 + != OpenSHC::Game::GM_EDITOR))) { + if ((this->LogicLayer[this->DAT_SomeTile] + & L_DEFAULT_EARTH_OR_TEXTURE) + == 0) + goto LAB_00510585; + this->GfxLayer[this->DAT_SomeTile] = 0; + } else { + if (DAT_BuildingsState::instance.buildings[iVar13] + .buildingType + == OpenSHC::Map::Buildings::BT_SIEGETOWER_PLACED) + goto LAB_00510585; + if (DAT_BuildingsState::instance.buildings[iVar13] + .currentTilePositionAdjusted + == this->DAT_SomeTile) { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func:: + updateBuildingGraphicsLayer, + this)(iVar13); + goto LAB_005109e8; + } + } + goto LAB_0050c199; + } + if ((this->LogicLayer[this->DAT_SomeTile] & L_KEEP_NON_MANOR_HOUSE) + == 0) { + if ((this->LogicLayer[this->DAT_SomeTile] & L_ROCKY) == 0 + || (this->LogicLayer[this->DAT_SomeTile] + & L_WALL_OR_GATEHOUSE) + != 0) { + if ((this->LogicLayer[this->DAT_SomeTile] & L_BOULDERS) + == 0) { + if ((this->LogicLayer[this->DAT_SomeTile] & L_PEBBLES) + == 0) { + if ((this->LogicLayer[this->DAT_SomeTile] & L_IRON) + == 0) { + if ((this->LogicLayer[this->DAT_SomeTile] + & L_OIL) + == 0) { + if ((this->LogicLayer[this->DAT_SomeTile] + & L_MOAT) + == 0) { + if ((this->LogicLayer[this + ->DAT_SomeTile] + & L_WALL_OR_GATEHOUSE + | L_FARM_FIELD_WHEAT + | L_FARM_FIELD_HOP + | L_FARM_FIELD_APPLE + | L_FARM_FIELD_DAIRY) + == 0 + || (this->LogicLayer[this + ->DAT_SomeTile] + & L_FARM_FIELD_APPLE) + != 0) { + sVar8 = 0; + if ((this->WallOwnerLayer[this + ->DAT_SomeTile] + & 8) + != 0) { + sVar8 = 0x2d; + } + if (((short)this->MiscDisplayLayer + [this->DAT_SomeTile] + & 0x80) + != 0) + goto LAB_0050ffbc; + if ((this->LogicLayer[this + ->DAT_SomeTile] + & L_WALL_OR_GATEHOUSE + | L_BUILDING + | L_KEEP_NON_MANOR_HOUSE) + != 0 + || this->BuildingWasLayer[this + ->DAT_SomeTile] + == '\0' + || ((short)this->MiscDisplayLayer + [this->DAT_SomeTile] + & 0x10) + == 0) + goto LAB_00510585; + } + } else { + this->bitFlag = 0; + for (local_d4 = 0; local_d4 < 8; + local_d4 = local_d4 + 2) { + iVar13 = this->DAT_SomeTile + + this->directionTranslationMatrix + [this->DAT_SomeY] + [local_d4]; + if ((this->LogicLayer[iVar13] + & L_MOAT) + == 0) { + if (this->BuildingLayer[iVar13] + != 0 + && DAT_BuildingsState::instance + .buildings[this + ->BuildingLayer + [iVar13]] + .buildingType + == OpenSHC::Map:: + Buildings:: + BT_DRAWBRIDGE + && (iVar13 + = MACRO_CALL_MEMBER( + OpenSHC::Map:: + TileMapState_Func:: + returnOwnedMoatAtTile, + this)(iVar13), + iVar13 != 0)) { + this->bitFlag + = this->bitFlag + | (byte)(0x80 + >> ((byte)local_d4 + & 0x1f)); + } + } else { + this->bitFlag = this->bitFlag + | (byte)(0x80 + >> ((byte)local_d4 + & 0x1f)); + } + } + this->bitFlag = ~this->bitFlag & 0xaa; + if (this->bitFlag == 0) { + this->bitFlag = 0; + for (local_d4 = 1; local_d4 < 8; + local_d4 = local_d4 + 2) { + iVar13 = this->DAT_SomeTile + + this->directionTranslationMatrix + [this->DAT_SomeY] + [local_d4]; + if ((this->LogicLayer[iVar13] + & L_MOAT) + == 0) { + if (this->BuildingLayer + [iVar13] + != 0 + && DAT_BuildingsState::instance + .buildings[this->BuildingLayer + [iVar13]] + .buildingType + == OpenSHC::Map:: + Buildings:: + BT_DRAWBRIDGE + && (iVar13 + = MACRO_CALL_MEMBER( + OpenSHC::Map:: + TileMapState_Func:: + returnOwnedMoatAtTile, + this)(iVar13), + iVar13 != 0)) { + this->bitFlag + = this->bitFlag + | (byte)(0x80 + >> ((byte) + local_d4 + & 0x1f)); + } + } else { + this->bitFlag + = this->bitFlag + | (byte)(0x80 + >> ((byte)local_d4 + & 0x1f)); + } + } + this->bitFlag + = ~this->bitFlag & 0x55; + } + if (this->mapOrientation == 0) { + this->bitFlag = MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation:: + DirectionAlgorithmState_Func:: + rotateByteLeft, + DAT_DirectionAlgorithmState:: + ptr)(this->bitFlag, 0); + } else if (this->mapOrientation == 2) { + this->bitFlag = MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation:: + DirectionAlgorithmState_Func:: + rotateByteLeft, + DAT_DirectionAlgorithmState:: + ptr)(this->bitFlag, 2); + } else if (this->mapOrientation == 4) { + this->bitFlag = MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation:: + DirectionAlgorithmState_Func:: + rotateByteLeft, + DAT_DirectionAlgorithmState:: + ptr)(this->bitFlag, 4); + } else if (this->mapOrientation == 6) { + this->bitFlag = MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation:: + DirectionAlgorithmState_Func:: + rotateByteLeft, + DAT_DirectionAlgorithmState:: + ptr)(this->bitFlag, 6); + } + this->GfxLayer[this->DAT_SomeTile] + = (short)GMTotalPicturesProcessed:: + instance[5] + + 0xcc + + (ushort)this->LuminesenceLayer + [this->DAT_SomeTile] + * 4 + + ((short)this->RandomLayer[this + ->DAT_SomeTile] + & 3); + for (local_14 = 0; local_14 < 7; + local_14 = local_14 + 1) { + if (DAT_TerrainDefinedData::instance + .TerrainFlagGraphicLookup + [local_14] + .unk1 + == this->bitFlag) { + sVar4 = (short) + GMTotalPicturesProcessed:: + instance[5]; + if (local_14 < 4) { + this->GfxLayer[this + ->DAT_SomeTile] + = sVar4 + 0xec + + (ushort)this->LuminesenceLayer + [this->DAT_SomeTile] + * 4 + + (ushort)DAT_TerrainDefinedData:: + instance + .TerrainFlagGraphicLookup + [local_14] + .unk2; + } else if (local_14 == 4) { + this->GfxLayer[this + ->DAT_SomeTile] + = sVar4 + 0x10c + + (ushort)this->LuminesenceLayer + [this->DAT_SomeTile] + * 4 + + ((short)this->RandomLayer + [this->DAT_SomeTile] + & 3); + } else if (local_14 == 5) { + this->GfxLayer[this + ->DAT_SomeTile] + = sVar4 + 300 + + (ushort)this->LuminesenceLayer + [this->DAT_SomeTile] + * 4 + + ((short)this->RandomLayer + [this->DAT_SomeTile] + & 3); + } else if (local_14 == 6) { + this->GfxLayer[this + ->DAT_SomeTile] + = sVar4 + 0x14c + + (ushort)this->LuminesenceLayer + [this->DAT_SomeTile]; + } + break; + } + } + if (((short)this->MiscDisplayLayer[this + ->DAT_SomeTile] + & 0x80) + != 0) { + LAB_0050ffbc: + uVar12 + = (0xdU - this->mapOrientation) + % 8; + uVar15 = (9 - this->mapOrientation) + % 8; + iVar13 = this->DAT_SomeTile + + this->directionTranslationMatrix + [this->DAT_SomeY][uVar15]; + uVar2 = (ushort)iVar17; + uVar3 = (ushort)this->DAT_SomeY; + if (((short)this->MiscDisplayLayer + [this->DAT_SomeTile + + this->directionTranslationMatrix + [this->DAT_SomeY] + [uVar12]] + & 0x80) + == 0) { + if (((short)this + ->MiscDisplayLayer + [iVar13] + & 0x80) + == 0) { + this->AlphaGFXLayer[this + ->DAT_SomeTile] + = this->AlphaGFXLayer[this + ->DAT_SomeTile] + + ((uVar2 ^ uVar3) & 1); + } else if ((this->mapOrientation + == 0) + || (this->mapOrientation + == 4)) { + this->AlphaGFXLayer[this + ->DAT_SomeTile] + = ((uVar2 ^ uVar3) & 1) + + 0x33 + sVar8; + } else { + this->AlphaGFXLayer[this + ->DAT_SomeTile] + = ((uVar2 ^ uVar3) & 1) + + 0x35 + sVar8; + } + } else if ( + ((short)this->MiscDisplayLayer + [iVar13] + & 0x80) + == 0) { + if ((this->mapOrientation == 0) + || (this->mapOrientation + == 4)) { + this->AlphaGFXLayer[this + ->DAT_SomeTile] + = ((uVar2 ^ uVar3) & 1) + + 0x35 + sVar8; + } else { + this->AlphaGFXLayer[this + ->DAT_SomeTile] + = ((uVar2 ^ uVar3) & 1) + + 0x33 + sVar8; + } + } else if ((this->mapOrientation + == 0) + || (this->mapOrientation + == 6)) { + uVar12 + = (int)this->DAT_SomeY % 8; + this->AlphaGFXLayer[this + ->DAT_SomeTile] + = (0x3e - (short)uVar12) + + sVar8; + } else { + uVar12 + = (int)this->DAT_SomeY % 8; + this->AlphaGFXLayer[this + ->DAT_SomeTile] + = (short)uVar12 + 0x37 + + sVar8; + } + MACRO_NEIGHBOUR_FLAGS_LOGIC_8( + r2, 0x200) + if (this->bitFlag != 0) { + switch (this->mapOrientation) { + case 0: + if ((this->bitFlag & 0x82) + == 0x82) { + this->AlphaGFXLayer[this + ->DAT_SomeTile] + = this->AlphaGFXLayer + [this->DAT_SomeTile] + + 0xe; + } + break; + case 2: + if ((this->bitFlag & 0xa0) + == 0xa0) { + this->AlphaGFXLayer[this + ->DAT_SomeTile] + = this->AlphaGFXLayer + [this->DAT_SomeTile] + + 0xe; + } + break; + case 4: + if ((this->bitFlag & 0x28) + == 0x28) { + this->AlphaGFXLayer[this + ->DAT_SomeTile] + = this->AlphaGFXLayer + [this->DAT_SomeTile] + + 0xe; + } + break; + case 6: + if ((this->bitFlag & 10) + == 10) { + this->AlphaGFXLayer[this + ->DAT_SomeTile] + = this->AlphaGFXLayer + [this->DAT_SomeTile] + + 0xe; + } + } + } + if ((this->LogicLayer[this + ->DAT_SomeTile] + & L_PLAIN2_AND_PITCH + | L_MOAT) + == 0) + goto LAB_00510585; + } + } + } else { + this->PillarGFXLayer[this + ->DAT_SomeTile] = (ushort) + GMTotalPicturesProcessed::instance[9]; + this->wallCornerRotation + = (int)(short)this + ->RandomLayer[this->DAT_SomeTile] + & 7; + this->GfxLayer[this->DAT_SomeTile] + = (short)GMTotalPicturesProcessed:: + instance[0x37] + + 0x428 + + (short)(this->wallCornerRotation + << 4); + sVar4 = (short)this->DAT_SomeY; + sVar5 = (short)this->DAT_SomeX; + if (this->wallCornerRotation == 0) { + this->WallGFXLayer[this->DAT_SomeTile] + = (short)this->RandomLayer[this + ->DAT_SomeTile] + + sVar5 + sVar4 + & 0x1ff; + } else if (this->wallCornerRotation == 1) { + this->WallGFXLayer[this->DAT_SomeTile] + = (short)this->RandomLayer[this + ->DAT_SomeTile] + + sVar5 + sVar4 + & 0x1ff; + } else if (this->wallCornerRotation == 2) { + this->WallGFXLayer[this->DAT_SomeTile] + = (short)this->RandomLayer[this + ->DAT_SomeTile] + + sVar5 + sVar4 + & 0x7f; + } else if (this->wallCornerRotation == 3) { + this->WallGFXLayer[this->DAT_SomeTile] + = (short)this->RandomLayer[this + ->DAT_SomeTile] + + sVar5 + sVar4 + & 0x7f; + } else if (this->wallCornerRotation == 4) { + this->WallGFXLayer[this->DAT_SomeTile] + = (short)this->RandomLayer[this + ->DAT_SomeTile] + + sVar5 + sVar4 + & 0xff; + } else if (this->wallCornerRotation == 5) { + this->WallGFXLayer[this->DAT_SomeTile] + = (short)this->RandomLayer[this + ->DAT_SomeTile] + + sVar5 + sVar4 + & 0xff; + } else if (this->wallCornerRotation == 6) { + this->WallGFXLayer[this->DAT_SomeTile] + = (short)this->RandomLayer[this + ->DAT_SomeTile] + + sVar5 + sVar4 + & 0x7f; + } else if (this->wallCornerRotation == 7) { + this->WallGFXLayer[this->DAT_SomeTile] + = (short)this->RandomLayer[this + ->DAT_SomeTile] + + sVar5 + sVar4 + & 0x7f; + } + } + } else { + MACRO_CALL_MEMBER( + OpenSHC::Map::TileMapState_Func:: + computeClimbRampRotation, + this)(this->DAT_SomeTile, + (uint)(this->DAT_SomeX), + (uint)(this->DAT_SomeY)); + this->PillarGFXLayer[this->DAT_SomeTile] + = (short) + GMTotalPicturesProcessed::instance[9] + - 1 + (short)this->wallCornerRotation; + this->MiscDisplayLayer[this->DAT_SomeTile] + = (short)this + ->MiscDisplayLayer[this->DAT_SomeTile] + | 0x800; + this->wallCornerRotation + = (int)(short)this + ->RandomLayer[this->DAT_SomeTile] + & 0xf; + this->GfxLayer[this->DAT_SomeTile] + = (short)GMTotalPicturesProcessed::instance + [0xc] + + 0xee + (short)this->wallCornerRotation; + } + } else { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func:: + computeClimbRampRotation, + this)(this->DAT_SomeTile, + (uint)(this->DAT_SomeX), + (uint)(this->DAT_SomeY)); + this->PillarGFXLayer[this->DAT_SomeTile] + = (short)GMTotalPicturesProcessed::instance[9] + - 1 + (short)this->wallCornerRotation; + this->MiscDisplayLayer[this->DAT_SomeTile] + = (short)this + ->MiscDisplayLayer[this->DAT_SomeTile] + | 0x800; + this->wallCornerRotation + = (int)(short)this + ->RandomLayer[this->DAT_SomeTile] + & 0xf; + if (this->LuminesenceLayer[this->DAT_SomeTile] + < 6) { + this->GfxLayer[this->DAT_SomeTile] + = (short)GMTotalPicturesProcessed::instance + [0xc] + + 0x20 + (short)this->wallCornerRotation; + } else { + this->GfxLayer[this->DAT_SomeTile] + = (short)GMTotalPicturesProcessed::instance + [0xc] + + 0x30 + (short)this->wallCornerRotation; + } + } + } else { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func:: + computeClimbRampRotation, + this)(this->DAT_SomeTile, (uint)(this->DAT_SomeX), + (uint)(this->DAT_SomeY)); + this->PillarGFXLayer[this->DAT_SomeTile] + = (short)GMTotalPicturesProcessed::instance[9] - 1 + + (short)this->wallCornerRotation; + this->MiscDisplayLayer[this->DAT_SomeTile] + = (short)this->MiscDisplayLayer[this->DAT_SomeTile] + | 0x800; + this->wallCornerRotation + = (int)(short)this->RandomLayer[this->DAT_SomeTile] + & 0xf; + if (this->LuminesenceLayer[this->DAT_SomeTile] < 6) { + this->GfxLayer[this->DAT_SomeTile] + = (short)GMTotalPicturesProcessed::instance[0xc] + + 0x40 + (short)this->wallCornerRotation; + } else { + this->GfxLayer[this->DAT_SomeTile] + = (short)GMTotalPicturesProcessed::instance[0xc] + + 0x50 + (short)this->wallCornerRotation; + } + } + } else { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func:: + computeClimbRampRotation, + this)(this->DAT_SomeTile, (uint)(this->DAT_SomeX), + (uint)(this->DAT_SomeY)); + this->PillarGFXLayer[this->DAT_SomeTile] + = (short)GMTotalPicturesProcessed::instance[9] - 1 + + (short)this->wallCornerRotation; + this->MiscDisplayLayer[this->DAT_SomeTile] + = (short)this->MiscDisplayLayer[this->DAT_SomeTile] + | 0x800; + iVar13 = (int)this->OrganismLayer[this->DAT_SomeTile]; + if (1999 < iVar13) { + if (*(int*)(&DAT_LandscapeState::instance.trees[0x635] + .unknownDistanceRelatedToCrow + + iVar13 * 0x10) + == this->DAT_SomeTile) { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func:: + applyRockGraphicsToFootprint, + this)(iVar13 + -2000); + } + goto LAB_0050c199; + } + this->wallCornerRotation + = (int)(short)this->RandomLayer[this->DAT_SomeTile] & 7; + this->GfxLayer[this->DAT_SomeTile] + = (short)GMTotalPicturesProcessed::instance[0x38] + + (ushort)this->LuminesenceLayer[this->DAT_SomeTile] * 8 + + (short)this->wallCornerRotation; + } + } else { + if (DAT_BuildingsState::instance + .buildings[this->BuildingLayer[this->DAT_SomeTile]] + .currentTilePositionAdjusted + != this->DAT_SomeTile) + goto LAB_0050c199; + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func:: + updateBuildingGraphicsLayer, + this)((int)this->BuildingLayer[this->DAT_SomeTile]); + } + } else { + this->MiscDisplayLayer[this->DAT_SomeTile] + = (short)this->MiscDisplayLayer[this->DAT_SomeTile] & 0xdfff; + iVar13 = MACRO_CALL_MEMBER( + OpenSHC::Map::TileMapState_Func::getPitchDitchIDForTile, this)( + this->DAT_SomeTile); + if (iVar13 != 0) { + if (this->pitchDitches[iVar13].state < 2 + && (BVar11 = MACRO_CALL_MEMBER( + OpenSHC::Game::GameStateStructures_Func::isSameTeam, + DAT_GameState::ptr)( + (int)this->pitchDitches[iVar13].owner, + (int)(DAT_GameSynchronyState::instance + .currentPlayerSlotID)), + BVar11 == FALSE) + && DAT_GameCore::instance.gameMode_2 + != OpenSHC::Game::GM_EDITOR) { + if ((this->LogicLayer[this->DAT_SomeTile] + & L_DEFAULT_EARTH_OR_TEXTURE) + == 0) + goto LAB_00510585; + this->GfxLayer[this->DAT_SomeTile] = 0; + } else { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func:: + computeClimbRampRotation, + this)(this->DAT_SomeTile, (uint)(iVar17), + (uint)(this->DAT_SomeY)); + this->PillarGFXLayer[this->DAT_SomeTile] + = (short)GMTotalPicturesProcessed::instance[9] - 1 + + (short)this->wallCornerRotation; + this->MiscDisplayLayer[this->DAT_SomeTile] + = (short)this->MiscDisplayLayer[this->DAT_SomeTile] + | 0x800; + this->GfxLayer[this->DAT_SomeTile] + = (this->pitchDitches[iVar13].rng & 7U) + + (short)GMTotalPicturesProcessed::instance[0x8c]; + this->MiscDisplayLayer[this->DAT_SomeTile] + = (short)this->MiscDisplayLayer[this->DAT_SomeTile] + | 0x2000; + if (((short)this->MiscDisplayLayer[this->DAT_SomeTile] + & 0x80) + != 0) + goto LAB_0050ffbc; + } + goto LAB_0050c199; + } + LAB_00510585: + uVar12 + = (((int)(uint)this->HeightLayer[this->DAT_SomeTile] >> 3) - 1) + % 16; + local_8 = uVar12 * 0x40 + 1; + iVar13 = MACRO_CALL_MEMBER( + OpenSHC::Map::TileMapState_Func::computeClimbRampRotation, + this)( + this->DAT_SomeTile, (uint)(iVar17), (uint)(this->DAT_SomeY)); + if ((this->HeightLayer[this->DAT_SomeTile] < 0x88) + && (iVar13 == 0)) { + if (local_8 < 1) { + local_8 = 1; + } + this->PillarGFXLayer[this->DAT_SomeTile] + = (short)((local_8 - 1) / 2) + + (short)GMTotalPicturesProcessed::instance[3] + + (ushort)this->LuminesenceLayer[this->DAT_SomeTile] * 4 + + ((short)this->RandomLayer[this->DAT_SomeTile] & 3); + BVar11 = MACRO_CALL_MEMBER( + OpenSHC::Map::TileMapState_Func::isCliffDropInDirection, + this)(this->DAT_SomeTile, (undefined4)((int)(iVar17)), + this->DAT_SomeY); + if (BVar11 == FALSE) { + bVar10 = false; + } else { + bVar10 = true; + } + } else { + this->PillarGFXLayer[this->DAT_SomeTile] + = (short)GMTotalPicturesProcessed::instance[9] - 1 + + (short)this->wallCornerRotation; + this->MiscDisplayLayer[this->DAT_SomeTile] + = (short)this->MiscDisplayLayer[this->DAT_SomeTile] | 0x800; + bVar10 = true; + } + if (((char)this->Logic2Layer[this->DAT_SomeTile] & 0x20) == 0) { + if (this->HeightLayer[this->DAT_SomeTile] < 8) { + if (((char)this->Logic2Layer[this->DAT_SomeTile] & 2) + == 0) { + this->GfxLayer[this->DAT_SomeTile] + = (short)GMTotalPicturesProcessed::instance[2] + + (ushort)this->LuminesenceLayer[this->DAT_SomeTile] + * 4 + + ((short)this->RandomLayer[this->DAT_SomeTile] + & 3); + } else { + this->GfxLayer[this->DAT_SomeTile] + = (short)GMTotalPicturesProcessed::instance[0x37] + + 0xb4 + + ((short)this->RandomLayer[this->DAT_SomeTile] + & 7); + } + } else if ((this->LogicLayer[this->DAT_SomeTile] + & L_DEFAULT_EARTH_OR_TEXTURE) + == 0) { + if ((bVar10) + && (DAT_GameCore::instance.gameMode_2 + == OpenSHC::Game::GM_EDITOR)) { + this->LogicLayer[this->DAT_SomeTile] + = this->LogicLayer[this->DAT_SomeTile] | 128; + this->GfxLayer[this->DAT_SomeTile] + = (short)GMTotalPicturesProcessed::instance[0x38] + + (ushort)this->LuminesenceLayer[this->DAT_SomeTile] + * 8 + + ((short)this->RandomLayer[this->DAT_SomeTile] + & 7); + } else { + this->GfxLayer[this->DAT_SomeTile] + = (short)GMTotalPicturesProcessed::instance[2] + + ((short)((int)(uint)this + ->HeightLayer[this->DAT_SomeTile] + >> 3) + - 1) + * 0x20 + + (ushort)this->LuminesenceLayer[this->DAT_SomeTile] + * 4 + + ((short)this->RandomLayer[this->DAT_SomeTile] + & 3); + } + } else { + /* + sets section 1001 after placing oasis grass for example + */ + this->GfxLayer[this->DAT_SomeTile] = 0; + } + } else { + this->GfxLayer[this->DAT_SomeTile] = 0; + } + } + } else { + MACRO_NEIGHBOUR_FLAGS_LOGIC_4(c1, NEIGHBOUR_FLAGS_MASK_RIVER_OR_FORD) + bVar19 = this->bitFlag; + this->bitFlag = ~bVar19 & 0xaa; + if (this->bitFlag == 0) { + MACRO_NEIGHBOUR_FLAGS_LOGIC_8( + d1, NEIGHBOUR_FLAGS_MASK_RIVER_OR_FORD) + this->bitFlag = ~this->bitFlag; + this->bitFlag = this->bitFlag & 0x55; + } + if (this->mapOrientation == 0) { + this->bitFlag = MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::DirectionAlgorithmState_Func:: + rotateByteLeft, + DAT_DirectionAlgorithmState::ptr)(this->bitFlag, 0); + } else if (this->mapOrientation == 2) { + this->bitFlag = MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::DirectionAlgorithmState_Func:: + rotateByteLeft, + DAT_DirectionAlgorithmState::ptr)(this->bitFlag, 2); + } else if (this->mapOrientation == 4) { + this->bitFlag = MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::DirectionAlgorithmState_Func:: + rotateByteLeft, + DAT_DirectionAlgorithmState::ptr)(this->bitFlag, 4); + } else if (this->mapOrientation == 6) { + this->bitFlag = MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::DirectionAlgorithmState_Func:: + rotateByteLeft, + DAT_DirectionAlgorithmState::ptr)(this->bitFlag, 6); + } + this->GfxLayer[this->DAT_SomeTile] + = (short)GMTotalPicturesProcessed::instance[5] + 0x29c + + (ushort)this->LuminesenceLayer[this->DAT_SomeTile] * 8 + + ((short)this->RandomLayer[this->DAT_SomeTile] & 7); + for (local_14 = 0; local_14 < 7; local_14 = local_14 + 1) { + if (DAT_TerrainDefinedData::instance + .TerrainFlagGraphicLookup[local_14] + .unk1 + == this->bitFlag) { + sVar4 = (short)GMTotalPicturesProcessed::instance[5]; + if (local_14 < 4) { + this->GfxLayer[this->DAT_SomeTile] = sVar4 + 0x234 + + (ushort)this->LuminesenceLayer[this->DAT_SomeTile] * 4 + + (ushort)DAT_TerrainDefinedData::instance + .TerrainFlagGraphicLookup[local_14] + .unk2; + } else if (local_14 == 4) { + this->GfxLayer[this->DAT_SomeTile] = sVar4 + 0x254 + + (ushort)this->LuminesenceLayer[this->DAT_SomeTile] * 4 + + ((short)this->RandomLayer[this->DAT_SomeTile] & 3); + } else if (local_14 == 5) { + this->GfxLayer[this->DAT_SomeTile] = sVar4 + 0x274 + + (ushort)this->LuminesenceLayer[this->DAT_SomeTile] * 4 + + ((short)this->RandomLayer[this->DAT_SomeTile] & 3); + } else if (local_14 == 6) { + this->GfxLayer[this->DAT_SomeTile] = sVar4 + 0x294 + + (ushort)this->LuminesenceLayer[this->DAT_SomeTile]; + } + break; + } + } + } + } else { + this->Logic2Layer[this->DAT_SomeTile] + = (char)this->Logic2Layer[this->DAT_SomeTile] & 0xf7; + MACRO_NEIGHBOUR_FLAGS_LOGIC_4(c2, 1) + bVar19 = this->bitFlag; + if (bVar19 != 0 + && (this->Logic2Layer[this->DAT_SomeTile] + = (char)this->Logic2Layer[this->DAT_SomeTile] | 8, + ((char)this->Logic2Layer[this->DAT_SomeTile] & 0x20) != 0)) { + this->Logic2Layer[this->DAT_SomeTile] + = (char)this->Logic2Layer[this->DAT_SomeTile] & 0xdf; + this->WallGFXLayer[this->DAT_SomeTile] + = (short)this->RandomLayer[this->DAT_SomeTile] & 7; + } + MACRO_NEIGHBOUR_FLAGS_LOGIC_4(c3, 0x100031) + bVar19 = this->bitFlag; + this->bitFlag = ~bVar19 & 0xaa; + if (this->bitFlag == 0) { + MACRO_NEIGHBOUR_FLAGS_LOGIC_8(d2, 0x100031) + this->bitFlag = ~this->bitFlag; + this->bitFlag = this->bitFlag & 0x55; + } + if (this->mapOrientation == 0) { + this->bitFlag = MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::DirectionAlgorithmState_Func:: + rotateByteLeft, + DAT_DirectionAlgorithmState::ptr)(this->bitFlag, 0); + } else if (this->mapOrientation == 2) { + this->bitFlag = MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::DirectionAlgorithmState_Func:: + rotateByteLeft, + DAT_DirectionAlgorithmState::ptr)(this->bitFlag, 2); + } else if (this->mapOrientation == 4) { + this->bitFlag = MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::DirectionAlgorithmState_Func:: + rotateByteLeft, + DAT_DirectionAlgorithmState::ptr)(this->bitFlag, 4); + } else if (this->mapOrientation == 6) { + this->bitFlag = MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::DirectionAlgorithmState_Func:: + rotateByteLeft, + DAT_DirectionAlgorithmState::ptr)(this->bitFlag, 6); + } + MACRO_CALL_MEMBER( + OpenSHC::Map::TileMapState_Func::propagateCliffEdgeFlagFromNeighbor, + this)(this->DAT_SomeTile, iVar17, this->DAT_SomeY); + if ((char)this->Logic2Layer[this->DAT_SomeTile] == 0) { + this->GfxLayer[this->DAT_SomeTile] + = (short)GMTotalPicturesProcessed::instance[5] + 0x214 + + (ushort)this->LuminesenceLayer[this->DAT_SomeTile] * 4 + + ((short)this->RandomLayer[this->DAT_SomeTile] & 3); + for (local_14 = 0; local_14 < 7; local_14 = local_14 + 1) { + if (DAT_TerrainDefinedData::instance + .TerrainFlagGraphicLookup[local_14] + .unk1 + == this->bitFlag) { + MACRO_NEIGHBOUR_FLAGS_LOGIC_4(c4, 0x200000) + sVar4 = (short)GMTotalPicturesProcessed::instance[5]; + if (local_14 < 4) { + if (this->bitFlag == 0) { + this->GfxLayer[this->DAT_SomeTile] = sVar4 + 0x234 + + (ushort)this->LuminesenceLayer[this->DAT_SomeTile] + * 4 + + (ushort)DAT_TerrainDefinedData::instance + .TerrainFlagGraphicLookup[local_14] + .unk2; + } else { + this->GfxLayer[this->DAT_SomeTile] = sVar4 + 0x2dc + + (ushort)this->LuminesenceLayer[this->DAT_SomeTile] + * 4 + + (ushort)DAT_TerrainDefinedData::instance + .TerrainFlagGraphicLookup[local_14] + .unk2; + } + } else if (this->bitFlag == 0) { + if (local_14 == 4) { + this->GfxLayer[this->DAT_SomeTile] = sVar4 + 0x254 + + (ushort)this->LuminesenceLayer[this->DAT_SomeTile] + * 4 + + ((short)this->RandomLayer[this->DAT_SomeTile] + & 3); + } else if (local_14 == 5) { + this->GfxLayer[this->DAT_SomeTile] = sVar4 + 0x274 + + (ushort)this->LuminesenceLayer[this->DAT_SomeTile] + * 4 + + ((short)this->RandomLayer[this->DAT_SomeTile] + & 3); + } else if (local_14 == 6) { + this->GfxLayer[this->DAT_SomeTile] = sVar4 + 0x294 + + (ushort)this + ->LuminesenceLayer[this->DAT_SomeTile]; + } + } + break; + } + } + } + if (((char)this->Logic2Layer[this->DAT_SomeTile] & 0x20) != 0) { + sVar4 = (this->WallGFXLayer[this->DAT_SomeTile] & 8) * 8 + 0x38d; + sVar5 = (short)GMTotalPicturesProcessed::instance[5]; + if (this->mapOrientation == 0) { + this->GfxLayer[this->DAT_SomeTile] = sVar5 + sVar4 - 1 + + (short)((int)(this->WallGFXLayer[this->DAT_SomeTile] & 0x3e0) + >> 5) + * 8; + } else if (this->mapOrientation == 2) { + this->GfxLayer[this->DAT_SomeTile] = sVar5 + sVar4 - 1 + + ((short)((int)(this->WallGFXLayer[this->DAT_SomeTile] & 0x3e0) + >> 5) + - 2U + & 7) + * 8; + } else if (this->mapOrientation == 4) { + this->GfxLayer[this->DAT_SomeTile] = sVar5 + sVar4 - 1 + + ((short)((int)(this->WallGFXLayer[this->DAT_SomeTile] & 0x3e0) + >> 5) + - 4U + & 7) + * 8; + } else { + this->GfxLayer[this->DAT_SomeTile] = sVar5 + sVar4 - 1 + + ((short)((int)(this->WallGFXLayer[this->DAT_SomeTile] & 0x3e0) + >> 5) + - 6U + & 7) + * 8; + } + } + sVar4 = (short)GMTotalPicturesProcessed::instance[5]; + if (((char)this->Logic2Layer[this->DAT_SomeTile] & 0x50) == 0) { + if (((int)(char)this->Logic2Layer[this->DAT_SomeTile] & 0x88U) == 0) { + if (((char)this->Logic2Layer[this->DAT_SomeTile] & 1) == 0) { + if (((char)this->Logic2Layer[this->DAT_SomeTile] & 2) == 0) { + if (((char)this->Logic2Layer[this->DAT_SomeTile] & 4) + != 0) { + this->GfxLayer[this->DAT_SomeTile] = sVar4 + 0x41c; + } + } else { + this->GfxLayer[this->DAT_SomeTile] = sVar4 + 0x414; + } + } else { + this->GfxLayer[this->DAT_SomeTile] = sVar4 + 0x40c; + } + } else { + MACRO_NEIGHBOUR_FLAGS_LOGIC_8(m4, 1) + bVar19 = this->bitFlag; + MACRO_NEIGHBOUR_FLAGS_TERRAIN_8(r3, 0x50) + bVar16 = this->bitFlag; + this->bitFlag = bVar16 | bVar19; + local_c0 = 0xffffffff; + if (this->bitFlag == 0) { + MACRO_NEIGHBOUR_FLAGS_LOGIC_8(m5, 0x100000) + if (this->bitFlag != 0) { + for (local_14 = 0; local_14 < 8; local_14 = local_14 + 1) { + if (((uint)this->bitFlag & 1 << ((byte)local_14 & 0x1f)) + != 0 + && this->HeightLayer[this->DAT_SomeTile + + this->directionTranslationMatrix[this + ->DAT_SomeY][DAT_TerrainDefinedData:: + instance.field2344_0x370c[local_14]]] + <= this->HeightLayer[this->DAT_SomeTile]) { + this->bitFlag = this->bitFlag + & ~(byte)(1 << ((byte)local_14 & 0x1f)); + } + } + if (this->bitFlag != 0) { + if ((this->bitFlag & 0x80) == 0) { + if ((this->bitFlag & 0x20) == 0) { + if ((this->bitFlag & 8) == 0) { + if ((this->bitFlag & 2) == 0) { + if (this->bitFlag == 0x41) { + local_c0 = 4; + } else if (this->bitFlag == 0x50) { + local_c0 = 6; + } else if (this->bitFlag == 0x14) { + local_c0 = 0; + } else if (this->bitFlag == 5) { + local_c0 = 2; + } else if ((this->bitFlag & 0x40) + == 0) { + if ((this->bitFlag & 1) == 0) { + if ((this->bitFlag & 4) == 0) { + if ((this->bitFlag & 0x10) + != 0) { + local_c0 = 7; + } + } else { + local_c0 = 1; + } + } else { + local_c0 = 3; + } + } else { + local_c0 = 5; + } + } else if ((this->bitFlag & 0x80) == 0) { + if ((this->bitFlag & 8) == 0) { + if ((this->bitFlag & 5) == 5) { + local_c0 = 2; + } else { + local_c0 = 2; + } + } else { + local_c0 = 1; + } + } else { + local_c0 = 3; + } + } else if ((this->bitFlag & 2) == 0) { + if ((this->bitFlag & 0x20) == 0) { + if ((this->bitFlag & 0x14) == 0x14) { + local_c0 = 0; + } else { + local_c0 = 0; + } + } else { + local_c0 = 7; + } + } else { + local_c0 = 1; + } + } else if ((this->bitFlag & 8) == 0) { + if ((this->bitFlag & 0x80) == 0) { + if ((this->bitFlag & 0x50) == 0x50) { + local_c0 = 6; + } else { + local_c0 = 6; + } + } else { + local_c0 = 5; + } + } else { + local_c0 = 7; + } + } else if ((this->bitFlag & 0x20) == 0) { + if ((this->bitFlag & 2) == 0) { + if ((this->bitFlag & 0x41) == 0x41) { + local_c0 = 4; + } else { + local_c0 = 4; + } + } else { + local_c0 = 3; + } + } else { + local_c0 = 5; + } + local_c0 = ((local_c0 - this->mapOrientation) + 8) % 8; + this->GfxLayer[this->DAT_SomeTile] + = sVar4 + 0x30c + (short)(local_c0 << 4); + } + } + if (local_c0 == 0xffffffff) { + this->GfxLayer[this->DAT_SomeTile] + = (short)GMTotalPicturesProcessed::instance[5] + 0x214 + + (ushort)this->LuminesenceLayer[this->DAT_SomeTile] * 4 + + ((short)this->RandomLayer[this->DAT_SomeTile] & 3); + this->Logic2Layer[this->DAT_SomeTile] + = (char)this->Logic2Layer[this->DAT_SomeTile] & 0x7f; + } + } else { + if ((this->bitFlag & 0x80) == 0) { + if ((this->bitFlag & 0x20) == 0) { + if ((this->bitFlag & 8) == 0) { + if ((this->bitFlag & 2) == 0) { + if (this->bitFlag == 0x40) { + local_c0 = 5; + } else if (this->bitFlag == 1) { + local_c0 = 3; + } else if (this->bitFlag == 4) { + local_c0 = 1; + } else if (this->bitFlag == 0x10) { + local_c0 = 7; + } else if (this->bitFlag == 0x41) { + local_c0 = 4; + } else if (this->bitFlag == 0x50) { + local_c0 = 6; + } else if (this->bitFlag == 0x14) { + local_c0 = 0; + } else if (this->bitFlag == 5) { + local_c0 = 2; + } + } else if ((this->bitFlag & 0x80) == 0) { + if ((this->bitFlag & 8) == 0) { + if ((this->bitFlag & 5) == 5) { + local_c0 = 2; + } else { + local_c0 = 2; + } + } else { + local_c0 = 1; + } + } else { + local_c0 = 3; + } + } else if ((this->bitFlag & 2) == 0) { + if ((this->bitFlag & 0x20) == 0) { + if ((this->bitFlag & 0x14) == 0x14) { + local_c0 = 0; + } else { + local_c0 = 0; + } + } else { + local_c0 = 7; + } + } else { + local_c0 = 1; + } + } else if ((this->bitFlag & 8) == 0) { + if ((this->bitFlag & 0x80) == 0) { + if ((this->bitFlag & 0x50) == 0x50) { + local_c0 = 6; + } else { + local_c0 = 6; + } + } else { + local_c0 = 5; + } + } else { + local_c0 = 7; + } + } else if ((this->bitFlag & 0x20) == 0) { + if ((this->bitFlag & 2) == 0) { + if ((this->bitFlag & 0x41) == 0x41) { + local_c0 = 4; + } else { + local_c0 = 4; + } + } else { + local_c0 = 3; + } + } else { + local_c0 = 5; + } + if (local_c0 == 0xffffffff) { + this->GfxLayer[this->DAT_SomeTile] = sVar4 + 0x214 + + (ushort)this->LuminesenceLayer[this->DAT_SomeTile] * 4 + + ((short)this->RandomLayer[this->DAT_SomeTile] & 3); + this->Logic2Layer[this->DAT_SomeTile] + = (char)this->Logic2Layer[this->DAT_SomeTile] & 0x7f; + } else { + uVar12 = ((local_c0 - this->mapOrientation) + 8) % 8; + this->GfxLayer[this->DAT_SomeTile] + = sVar4 + 0x30c + (short)(uVar12 << 4); + } + } + } + } else { + this->GfxLayer[this->DAT_SomeTile] = sVar4 + 0x2fc; + } + } + LAB_005109e8: + if ((this->LogicLayer[this->DAT_SomeTile] & 0x10000100U) != 0) { + bVar19 = this->DefaultHeightLayer[this->DAT_SomeTile]; + iVar17 = MACRO_CALL_MEMBER( + OpenSHC::Map::TileMapState_Func::computeClimbRampRotation, this)( + this->DAT_SomeTile, (uint)(iVar17), (uint)(this->DAT_SomeY)); + sVar5 = (short)GMTotalPicturesProcessed::instance[9]; + sVar4 = (short)this->wallCornerRotation; + if (this->DefaultHeightLayer[this->DAT_SomeTile] < 0x88) { + if (iVar17 == 0) { + if (((char)this->Logic2Layer[this->DAT_SomeTile] & 2) == 0) { + this->PillarGFXLayer[this->DAT_SomeTile] + = (short)(((((int)(uint)bVar19 >> 3) - 1) * 0x40) / 2) + + (short)GMTotalPicturesProcessed::instance[3] + + (ushort)this->LuminesenceLayer[this->DAT_SomeTile] * 4 + + ((short)this->RandomLayer[this->DAT_SomeTile] & 3); + } else { + this->PillarGFXLayer[this->DAT_SomeTile] = sVar5 - 1 + sVar4; + this->MiscDisplayLayer[this->DAT_SomeTile] + = (short)this->MiscDisplayLayer[this->DAT_SomeTile] | 0x800; + } + } else { + this->PillarGFXLayer[this->DAT_SomeTile] = sVar5 - 1 + sVar4; + this->MiscDisplayLayer[this->DAT_SomeTile] + = (short)this->MiscDisplayLayer[this->DAT_SomeTile] | 0x800; + } + } else { + this->PillarGFXLayer[this->DAT_SomeTile] = sVar5 - 1 + sVar4; + this->MiscDisplayLayer[this->DAT_SomeTile] + = (short)this->MiscDisplayLayer[this->DAT_SomeTile] | 0x800; + } + } + } else { + this->Logic2Layer[this->DAT_SomeTile] + = (char)this->Logic2Layer[this->DAT_SomeTile] & 0xf7; + MACRO_NEIGHBOUR_FLAGS_LOGIC_4(c5, 0x100000) + if (this->bitFlag == 0) { + if (((short)this->MiscDisplayLayer[this->DAT_SomeTile] & 0xc0) == 0) { + MACRO_NEIGHBOUR_FLAGS_MISC_8(m6, 0x40) + bVar19 = this->bitFlag; + MACRO_NEIGHBOUR_FLAGS_MISC_8(m7, 0x80) + bVar16 = this->bitFlag; + this->bitFlag = bVar16 & ~bVar19; + if (this->bitFlag != 0) { + this->GfxLayer[this->DAT_SomeTile] + = (short)GMTotalPicturesProcessed::instance[0xa6] + 0x5c4; + this->PillarGFXLayer[this->DAT_SomeTile] + = (ushort)GMTotalPicturesProcessed::instance[9]; + this->MiscDisplayLayer[this->DAT_SomeTile] + = (short)this->MiscDisplayLayer[this->DAT_SomeTile] | 0xc0; + } + } + if (2 < this->LuminesenceLayer[this->DAT_SomeTile]) { + this->MiscDisplayLayer[this->DAT_SomeTile] + = (short)this->MiscDisplayLayer[this->DAT_SomeTile] & 0xffbf; + this->MiscDisplayLayer[this->DAT_SomeTile] + = (short)this->MiscDisplayLayer[this->DAT_SomeTile] & 0xff7f; + } + local_38 = this->LuminesenceLayer[this->DAT_SomeTile] - 2; + if (local_38 < 0) { + local_38 = 0; + } + sVar4 = (short)local_38; + if (((short)this->MiscDisplayLayer[this->DAT_SomeTile] & 0xc0) == 0) { + if (((short)this->MiscDisplayLayer[this->DAT_SomeTile] & 0x100) == 0) { + MACRO_NEIGHBOUR_FLAGS_MISC_8(m8, 0x100) + if (this->bitFlag != 0) { + local_ac = 2; + uVar12 = (uint)this->bitFlag + << ((byte)this->mapOrientation & 0x1f); + uVar12 = uVar12 & 0xff | (int)uVar12 >> 8; + switch (uVar12) { + case 1: + local_b0 = 0x1c; + break; + case 2: + case 3: + case 6: + case 7: + local_b0 = 0xc; + local_ac = 4; + break; + case 4: + local_b0 = 0x1a; + break; + default: + local_b4 = 0; + for (local_b8 = 0; local_b8 < 8; local_b8 = local_b8 + 1) { + if ((1 << ((byte)local_b8 & 0x1f) & uVar12) != 0) { + local_b4 = local_b4 + 1; + } + } + if (local_b4 < 4) { + local_b0 = 0x20; + } else { + local_b0 = 0x21; + } + local_ac = 1; + break; + case 8: + case 0xc: + case 0x18: + case 0x1c: + local_b0 = 8; + local_ac = 4; + break; + case 0xe: + case 0xf: + case 0x1e: + case 0x1f: + local_b0 = 0x16; + break; + case 0x10: + local_b0 = 0x18; + break; + case 0x20: + case 0x30: + case 0x60: + case 0x70: + local_b0 = 4; + local_ac = 4; + break; + case 0x38: + case 0x3c: + case 0x78: + case 0x7c: + local_b0 = 0x14; + break; + case 0x40: + local_b0 = 0x1e; + break; + case 0x80: + case 0x81: + case 0xc0: + case 0xc1: + local_b0 = 0; + local_ac = 4; + break; + case 0x83: + case 0x87: + case 0xc3: + case 199: + local_b0 = 0x10; + break; + case 0xe0: + case 0xe1: + case 0xf0: + case 0xf1: + local_b0 = 0x12; + } + this->GfxLayer[this->DAT_SomeTile] + = (short)GMTotalPicturesProcessed::instance[0xa6] + + (short)((int)(short)this->RandomLayer[this->DAT_SomeTile] + % local_ac) + + local_b0 + 8 + sVar4 * 0xf6; + this->MiscDisplayLayer[this->DAT_SomeTile] + = (short)this->MiscDisplayLayer[this->DAT_SomeTile] | 0x200; + } + } else { + local_94 = 2; + uVar15 = (int)this->CertainPathLayer[this->DAT_SomeTile] & 0xff; + uVar12 = uVar15 << ((byte)this->mapOrientation & 0x1f); + uVar12 = uVar12 & 0xff | (int)uVar12 >> 8; + switch (uVar12) { + case 1: + local_9c = 0x1c; + break; + case 2: + case 3: + case 6: + case 7: + local_9c = 0xc; + local_94 = 4; + break; + case 4: + local_9c = 0x1a; + break; + default: + local_a0 = 0; + for (local_a4 = 0; local_a4 < 8; local_a4 = local_a4 + 1) { + if ((1 << ((byte)local_a4 & 0x1f) & uVar12) != 0) { + local_a0 = local_a0 + 1; + } + } + if (local_a0 < 4) { + local_9c = 0x20; + } else { + local_9c = 0x21; + } + local_94 = 1; + break; + case 8: + case 0xc: + case 0x18: + case 0x1c: + local_9c = 8; + local_94 = 4; + break; + case 0xe: + case 0xf: + case 0x1e: + case 0x1f: + local_9c = 0x16; + break; + case 0x10: + local_9c = 0x18; + break; + case 0x20: + case 0x30: + case 0x60: + case 0x70: + local_9c = 4; + local_94 = 4; + break; + case 0x38: + case 0x3c: + case 0x78: + case 0x7c: + local_9c = 0x14; + break; + case 0x40: + local_9c = 0x1e; + break; + case 0x80: + case 0x81: + case 0xc0: + case 0xc1: + local_9c = 0; + local_94 = 4; + break; + case 0x83: + case 0x87: + case 0xc3: + case 199: + local_9c = 0x10; + break; + case 0xe0: + case 0xe1: + case 0xf0: + case 0xf1: + local_9c = 0x12; + } + local_9c = (short)((int)(short)this->RandomLayer[this->DAT_SomeTile] + % local_94) + + local_9c; + if (uVar15 + != ((int)this->CertainPathLayer[this->DAT_SomeTile] >> 8 + & 0xffU)) { + local_9c = local_9c + 0x66; + } + this->GfxLayer[this->DAT_SomeTile] + = (short)GMTotalPicturesProcessed::instance[0xa6] + local_9c + + 0x2a + sVar4 * 0xf6; + } + } + if (((short)this->MiscDisplayLayer[this->DAT_SomeTile] & 0x3c0) == 0) { + this->GfxLayer[this->DAT_SomeTile] + = ((short)this->RandomLayer[this->DAT_SomeTile] & 7) + + (short)GMTotalPicturesProcessed::instance[0xa6] + sVar4 * 0xf6; + this->PillarGFXLayer[this->DAT_SomeTile] + = (ushort)GMTotalPicturesProcessed::instance[9]; + } + } else { + this->GfxLayer[this->DAT_SomeTile] + = (short)GMTotalPicturesProcessed::instance[5] + 0x2fc; + this->Logic2Layer[this->DAT_SomeTile] + = (char)this->Logic2Layer[this->DAT_SomeTile] | 8; + } + } + } + LAB_0050c199: + this->DAT_SomeX = this->DAT_SomeX + 1; + } + } + } + } + } + } + return; + } + +} +} + +#pragma optimize("", on) diff --git a/src/OpenSHC/Map/TileMapState/updateLogicalTileMapRelatedSections.cpp b/src/OpenSHC/Map/TileMapState/updateLogicalTileMapRelatedSections.cpp new file mode 100644 index 0000000000..3dc61e15a4 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/updateLogicalTileMapRelatedSections.cpp @@ -0,0 +1,343 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Map/Buildings/BuildingsState.func.hpp" +#include "OpenSHC/Map/Buildings/BuildingType.hpp" + +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_PathFindingState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L2_BEACH; + using OpenSHC::Map::LogicHelpers::L2_EARTH_AND_STONES; + using OpenSHC::Map::LogicHelpers::L2_OASIS_GRASS; + using OpenSHC::Map::LogicHelpers::L2_PLATEAU_HIGH; + using OpenSHC::Map::LogicHelpers::L2_PLATEAU_MEDIUM; + using OpenSHC::Map::LogicHelpers::L2_SCRUB; + using OpenSHC::Map::LogicHelpers::L2_STONES_OR_DRIVEN_SANDUnk; + using OpenSHC::Map::LogicHelpers::L_BORDER; + using OpenSHC::Map::LogicHelpers::L_BORDER_EDGE; + using OpenSHC::Map::LogicHelpers::L_BUILDING; + using OpenSHC::Map::LogicHelpers::L_CRENEL; + using OpenSHC::Map::LogicHelpers::L_DEFAULT_EARTH_OR_TEXTURE; + using OpenSHC::Map::LogicHelpers::L_FARM_FIELD_HOP; + using OpenSHC::Map::LogicHelpers::L_FARM_FIELD_WHEAT; + using OpenSHC::Map::LogicHelpers::L_KEEP_NON_MANOR_HOUSE; + using OpenSHC::Map::LogicHelpers::L_MOAT; + using OpenSHC::Map::LogicHelpers::L_RIVER; + using OpenSHC::Map::LogicHelpers::L_SEA; + using OpenSHC::Map::LogicHelpers::L_STAIRS; + using OpenSHC::Map::LogicHelpers::L_STOCKPILEUnk; + using OpenSHC::Map::LogicHelpers::L_TREE_VARIATION; + using OpenSHC::Map::LogicHelpers::L_WALL_OR_GATEHOUSE; + + using OpenSHC::Map::Buildings::BuildingType; + + // FUNCTION: STRONGHOLDCRUSADER 0x004F70F0 + void TileMapState::updateLogicalTileMapRelatedSections() + { + if (this->forceUpdateLogicalAndMiscDisplayLayers == 0) { + return; + } + this->forceUpdateLogicalAndMiscDisplayLayers = 0; + int tile = DAT_ViewportRenderState::instance.translationMatrix[DAT_PathFindingState::instance.mappingYRelated] + .firstTileOfRow; + DAT_BuildingsState::instance.field34_0x18e074 = 1; + for (int row = DAT_PathFindingState::instance.mappingYRelated; + row < 400 && row <= DAT_PathFindingState::instance.yLimit; row++) { + for (int column = 0; column < this->yArray1[row]; column++, tile++) { + if ((this->LogicLayer[tile] & (L_BORDER | L_BORDER_EDGE)) != 0 || this->ChangedLayer[tile] == 0) { + continue; + } + + int height = this->HeightLayer[tile]; + int screenY = this->heightBasedScreenYOffset[height]; + this->ShowHiLayer[tile] = '\0'; + this->MiscDisplayLayer[tile] = this->MiscDisplayLayer[tile] & 0xffef; + /* whether the tile draws its own texture or the default earth */ + if (height == 0) { + if (((this->LogicLayer[tile] & L_RIVER) == 0 && (this->Logic2Layer[tile] & L2_BEACH) != 0) + || (this->LogicLayer[tile] & L_MOAT) != 0) { + this->LogicLayer[tile] = this->LogicLayer[tile] | L_DEFAULT_EARTH_OR_TEXTURE; + } else { + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_DEFAULT_EARTH_OR_TEXTURE; + } + } else if (height < 9) { + this->LogicLayer[tile] = this->LogicLayer[tile] | L_DEFAULT_EARTH_OR_TEXTURE; + } else if ((this->Logic2Layer[tile] & L2_PLATEAU_MEDIUM) != 0 + || (this->Logic2Layer[tile] & L2_PLATEAU_HIGH) != 0 + || (this->Logic2Layer[tile] & L2_EARTH_AND_STONES) != 0 + || (this->Logic2Layer[tile] & L2_OASIS_GRASS) != 0 || (this->Logic2Layer[tile] & L2_SCRUB) != 0 + || (char)this->Logic2Layer[tile] < '\0' + || (this->Logic2Layer[tile] & L2_STONES_OR_DRIVEN_SANDUnk) != 0) { + this->LogicLayer[tile] = this->LogicLayer[tile] | L_DEFAULT_EARTH_OR_TEXTURE; + } else { + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_DEFAULT_EARTH_OR_TEXTURE; + } + + /* a tile level with all eight neighbours keeps its texture */ + for (int i = 0; i < 8; i++) { + int neighbour = this->directionTranslationMatrix[row][i] + tile; + if ((height > 8 || this->HeightLayer[neighbour] == 0) && height != this->HeightLayer[neighbour]) { + if ((this->LogicLayer[neighbour] & (L_RIVER | L_MOAT)) == 0) { + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_DEFAULT_EARTH_OR_TEXTURE; + } + break; + } + } + if (this->BuildingLayer[tile] != 0 + && DAT_BuildingsState::instance.buildings[this->BuildingLayer[tile]].buildingType + == OpenSHC::Map::Buildings::BT_DRAWBRIDGE) { + this->MiscDisplayLayer[tile] = this->MiscDisplayLayer[tile] | 0x10; + } + + if (this->disableElevationRendering == 0) { + /* look up the light's diagonal for anything standing high enough to shadow us */ + int walkTile = tile; + int* direction = this->directionTranslationMatrix[row] + this->screenSouthEastDirection; + bool shadowed = false; + for (int depth = 0; depth < 0x80; depth = depth + 0x10) { + walkTile = walkTile + *direction; + if ((this->LogicLayer[walkTile] & (L_BORDER | L_BORDER_EDGE)) != 0) { + break; + } + if (screenY <= (this->heightBasedScreenYOffset[this->HeightLayer[walkTile]] - depth) + -0x10) { + this->ShowHiLayer[tile] = 0xff; + shadowed = true; + break; + } + direction = direction + this->orientedRowStep * 8; + } + if (height == 0 || shadowed) { + continue; + } + } else { + this->ShowHiLayer[tile] = '\b'; + } + + bool occluded = true; + if ((this->LogicLayer[tile] & (L_BUILDING | L_KEEP_NON_MANOR_HOUSE)) == 0 + && (this->LogicLayer[tile] & L_TREE_VARIATION) == 0 + && (this->LogicLayer[tile] & L_FARM_FIELD_WHEAT) == 0 + && (this->LogicLayer[tile] & L_FARM_FIELD_HOP) == 0 && (this->LogicLayer[tile] & L_CRENEL) == 0 + && (this->LogicLayer[tile] & L_STAIRS) == 0) { + this->MiscDisplayLayer[tile] = this->MiscDisplayLayer[tile] | 0x10; + occluded = false; + } + for (int i = 0; i < 8; i++) { + int neighbour = this->directionTranslationMatrix[row][i] + tile; + if ((height > 8 && height != this->HeightLayer[neighbour]) + || (this->LogicLayer[neighbour] & L_TREE_VARIATION) != 0) { + this->MiscDisplayLayer[tile] = this->MiscDisplayLayer[tile] & 0xffef; + break; + } + if ((this->LogicLayer[neighbour] & L_FARM_FIELD_WHEAT) != 0) { + occluded = true; + } + if ((this->LogicLayer[neighbour] & L_FARM_FIELD_HOP) != 0) { + occluded = true; + } + } + this->MiscDisplayLayer[tile] = this->MiscDisplayLayer[tile] & 0xfffc; + + bool stepLeft = false; + bool stepRight = false; + int shadowTile = this->directionTranslationMatrix[row][this->screenSouthEastDirection] + tile; + int lowest = 0xfa; + if (this->heightBasedScreenYOffset[this->HeightLayer[shadowTile]] < 0xfa) { + lowest = this->heightBasedScreenYOffset[this->HeightLayer[shadowTile]]; + } + int nearly = screenY + 2; + if (nearly < this->heightBasedScreenYOffset[this->HeightLayer[shadowTile]]) { + occluded = true; + } + if ((this->LogicLayer[tile] & L_WALL_OR_GATEHOUSE) == 0) { + if ((this->LogicLayer[shadowTile] & (L_BUILDING | L_KEEP_NON_MANOR_HOUSE)) != 0 + && MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::getBuildingFlag1, + DAT_BuildingsState::ptr)(this->BuildingLayer[shadowTile]) + != 0) { + occluded = true; + } + int rightTile = this->directionTranslationMatrix[row][this->screenSouthDirection] + tile; + if (((this->LogicLayer[rightTile] & (L_BUILDING | L_KEEP_NON_MANOR_HOUSE)) != 0 + && MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::getBuildingFlag1, + DAT_BuildingsState::ptr)(this->BuildingLayer[rightTile]) + != 0) + || ((this->LogicLayer[rightTile] & L_WALL_OR_GATEHOUSE) != 0 + && (this->LogicLayer[rightTile] & L_STOCKPILEUnk) == 0)) { + occluded = true; + } + int leftTile = this->directionTranslationMatrix[row][this->screenEastDirection] + tile; + if (((this->LogicLayer[leftTile] & (L_BUILDING | L_KEEP_NON_MANOR_HOUSE)) != 0 + && MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::getBuildingFlag1, + DAT_BuildingsState::ptr)(this->BuildingLayer[leftTile]) + != 0) + || ((this->LogicLayer[leftTile] & L_WALL_OR_GATEHOUSE) != 0 + && (this->LogicLayer[leftTile] & L_STOCKPILEUnk) == 0)) { + occluded = true; + } + int rightTile2 + = this->directionTranslationMatrix[this->orientedRowStep + row][this->screenSouthDirection] + + shadowTile; + if (((this->LogicLayer[rightTile2] & (L_BUILDING | L_KEEP_NON_MANOR_HOUSE)) != 0 + && MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::getBuildingFlag1, + DAT_BuildingsState::ptr)(this->BuildingLayer[rightTile2]) + != 0) + || ((this->LogicLayer[rightTile2] & L_WALL_OR_GATEHOUSE) != 0 + && (this->LogicLayer[rightTile2] & L_STOCKPILEUnk) == 0)) { + occluded = true; + } + int leftTile2 + = this->directionTranslationMatrix[this->orientedRowStep + row][this->screenEastDirection] + + shadowTile; + if (((this->LogicLayer[leftTile2] & (L_BUILDING | L_KEEP_NON_MANOR_HOUSE)) != 0 + && MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::getBuildingFlag1, + DAT_BuildingsState::ptr)(this->BuildingLayer[leftTile2]) + != 0) + || ((this->LogicLayer[leftTile2] & L_WALL_OR_GATEHOUSE) != 0 + && (this->LogicLayer[leftTile2] & L_STOCKPILEUnk) == 0)) { + occluded = true; + } + shadowTile = shadowTile + + this->directionTranslationMatrix[this->orientedRowStep + row][this->screenSouthEastDirection]; + if ((this->LogicLayer[shadowTile] & (L_BUILDING | L_KEEP_NON_MANOR_HOUSE)) != 0 + && MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::getBuildingFlag1, + DAT_BuildingsState::ptr)(this->BuildingLayer[shadowTile]) + != 0) { + occluded = true; + } + int rightTile3 + = this->directionTranslationMatrix[row + this->orientedRowStep * 2][this->screenSouthDirection] + + shadowTile; + if (((this->LogicLayer[rightTile3] & (L_BUILDING | L_KEEP_NON_MANOR_HOUSE)) != 0 + && MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::getBuildingFlag1, + DAT_BuildingsState::ptr)(this->BuildingLayer[rightTile3]) + != 0) + || ((this->LogicLayer[rightTile3] & L_WALL_OR_GATEHOUSE) != 0 + && (this->LogicLayer[rightTile3] & L_STOCKPILEUnk) == 0)) { + occluded = true; + } + int leftTile3 + = this->directionTranslationMatrix[row + this->orientedRowStep * 2][this->screenEastDirection] + + shadowTile; + if (((this->LogicLayer[leftTile3] & (L_BUILDING | L_KEEP_NON_MANOR_HOUSE)) != 0 + && MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::getBuildingFlag1, + DAT_BuildingsState::ptr)(this->BuildingLayer[leftTile3]) + != 0) + || ((this->LogicLayer[leftTile3] & L_WALL_OR_GATEHOUSE) != 0 + && (this->LogicLayer[leftTile3] & L_STOCKPILEUnk) == 0)) { + occluded = true; + } + shadowTile = shadowTile + + this->directionTranslationMatrix[row + this->orientedRowStep * 2] + [this->screenSouthEastDirection]; + if ((this->LogicLayer[shadowTile] & (L_BUILDING | L_KEEP_NON_MANOR_HOUSE)) != 0 + && MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::getBuildingFlag1, + DAT_BuildingsState::ptr)(this->BuildingLayer[shadowTile]) + != 0) { + occluded = true; + } + } else { + if (DAT_BuildingsState::instance.buildings[this->BuildingLayer[shadowTile]].flag2 != 0) { + occluded = true; + } + if (DAT_BuildingsState::instance.buildings[this->BuildingLayer[shadowTile]].buildingType + == OpenSHC::Map::Buildings::BT_STOCKPILE) { + occluded = true; + } + if (DAT_BuildingsState::instance + .buildings[this->BuildingLayer[this->directionTranslationMatrix[this->orientedRowStep + + row][this->screenSouthEastDirection] + + shadowTile]] + .flag2 + != 0) { + occluded = true; + } + } + + int leftTile = this->directionTranslationMatrix[row][this->screenSouthDirection] + tile; + if (this->heightBasedScreenYOffset[this->HeightLayer[leftTile]] < lowest) { + lowest = this->heightBasedScreenYOffset[this->HeightLayer[leftTile]]; + } + if (screenY <= this->heightBasedScreenYOffset[this->HeightLayer[leftTile]]) { + stepLeft = true; + if (nearly < this->heightBasedScreenYOffset[this->HeightLayer[leftTile]]) { + occluded = true; + } + } + if ((this->LogicLayer[tile] & L_WALL_OR_GATEHOUSE) == 0) { + if ((this->LogicLayer[leftTile] & (L_BUILDING | L_KEEP_NON_MANOR_HOUSE)) != 0 + && MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::getBuildingFlag1, + DAT_BuildingsState::ptr)(this->BuildingLayer[leftTile]) + != 0) { + occluded = true; + } + } else { + if (DAT_BuildingsState::instance.buildings[this->BuildingLayer[leftTile]].flag2 != 0) { + occluded = true; + } + if (DAT_BuildingsState::instance.buildings[this->BuildingLayer[leftTile]].buildingType + == OpenSHC::Map::Buildings::BT_STOCKPILE) { + occluded = true; + } + } + + int rightTile = this->directionTranslationMatrix[row][this->screenEastDirection] + tile; + if (this->heightBasedScreenYOffset[this->HeightLayer[rightTile]] < lowest) { + lowest = this->heightBasedScreenYOffset[this->HeightLayer[rightTile]]; + } + if (screenY <= this->heightBasedScreenYOffset[this->HeightLayer[rightTile]]) { + stepRight = true; + if (nearly < this->heightBasedScreenYOffset[this->HeightLayer[rightTile]]) { + occluded = true; + } + } + bool clear; + if ((this->LogicLayer[tile] & L_WALL_OR_GATEHOUSE) == 0) { + if ((this->LogicLayer[tile] & L_KEEP_NON_MANOR_HOUSE) != 0 + || (this->LogicLayer[rightTile] & (L_BUILDING | L_KEEP_NON_MANOR_HOUSE)) == 0 + || MACRO_CALL_MEMBER(OpenSHC::Map::Buildings::BuildingsState_Func::getBuildingFlag1, + DAT_BuildingsState::ptr)(this->BuildingLayer[rightTile]) + == 0) { + clear = occluded; + } else { + clear = true; + } + } else { + if (DAT_BuildingsState::instance.buildings[this->BuildingLayer[rightTile]].flag2 != 0) { + occluded = true; + } + if (DAT_BuildingsState::instance.buildings[this->BuildingLayer[rightTile]].buildingType + == OpenSHC::Map::Buildings::BT_STOCKPILE) { + clear = true; + } else { + clear = occluded; + } + } + if (clear) { + this->MiscDisplayLayer[tile] = this->MiscDisplayLayer[tile] & 0xffef; + } else { + this->MiscDisplayLayer[tile] = this->MiscDisplayLayer[tile] | 0x10; + } + + if (lowest < screenY) { + if (this->disableElevationRendering == 0) { + this->ShowHiLayer[tile] = (char)screenY - (char)lowest; + } + if ((this->LogicLayer[tile] & L_SEA) == 0) { + if (stepLeft) { + this->MiscDisplayLayer[tile] = this->MiscDisplayLayer[tile] | 1; + } + if (stepRight) { + this->MiscDisplayLayer[tile] = this->MiscDisplayLayer[tile] | 2; + } + } + } + } + } + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/updateMacroLayer.cpp b/src/OpenSHC/Map/TileMapState/updateMacroLayer.cpp new file mode 100644 index 0000000000..c8bd742bc5 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/updateMacroLayer.cpp @@ -0,0 +1,38 @@ +#include "../TileMapState.func.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L2_BEACH; + using OpenSHC::Map::LogicHelpers::L2_EARTH_AND_STONES; + using OpenSHC::Map::LogicHelpers::L2_OASIS_GRASS; + using OpenSHC::Map::LogicHelpers::L2_PLATEAU_HIGH; + using OpenSHC::Map::LogicHelpers::L2_PLATEAU_MEDIUM; + using OpenSHC::Map::LogicHelpers::L2_SCRUB; + using OpenSHC::Map::LogicHelpers::L_DEFAULT_EARTH_OR_TEXTURE; + using OpenSHC::Map::LogicHelpers::L_MARSH; + using OpenSHC::Map::LogicHelpers::L_NONE; + + // FUNCTION: STRONGHOLDCRUSADER 0x00511020 + void TileMapState::updateMacroLayer() + { + if (this->forceUpdateMacroLayerFlag <= 0) { + return; + } + + this->forceUpdateMacroLayerFlag = 0; + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::updateMacroLayerRelated, this)( + L_DEFAULT_EARTH_OR_TEXTURE, L2_SCRUB, 0); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::updateMacroLayerRelated, this)(L_MARSH, L_NONE, 0); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::updateMacroLayerRelated, this)( + L_NONE, L2_EARTH_AND_STONES, 0); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::updateMacroLayerRelated, this)(L_NONE, L2_OASIS_GRASS, 0); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::updateMacroLayerRelated, this)(L_NONE, L2_BEACH, 0); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::updateMacroLayerRelated, this)(L_NONE, L2_PLATEAU_MEDIUM, 0); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::updateMacroLayerRelated, this)(L_NONE, L2_PLATEAU_HIGH, 0); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::updateMacroLayerRelated2, this)(); + this->forceUpdateTextureTilemap = 1; + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/updateMacroLayerRelated.cpp b/src/OpenSHC/Map/TileMapState/updateMacroLayerRelated.cpp new file mode 100644 index 0000000000..98669e6858 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/updateMacroLayerRelated.cpp @@ -0,0 +1,335 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" +#include "OpenSHC/Rendering/ViewportRenderState.func.hpp" +#include "OpenSHC/Map/TileMapState/NeighbourFlagsAsm.hpp" + +#include "OpenSHC/Globals/DAT_PathFindingState.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +// masks for the handwritten neighbour-flag macro; MASM has no "|", so these must be literals +#define NEIGHBOUR_FLAGS_MASK_DEFAULT_EARTH 0x8000 // L_DEFAULT_EARTH_OR_TEXTURE +#define NEIGHBOUR_FLAGS_MASK_MARSH 0x20000000 // L_MARSH +#define NEIGHBOUR_FLAGS_MASK_SEA 0x1 // L_SEA +#define NEIGHBOUR_FLAGS_MASK_L2_SCRUB 0x1 // L2_SCRUB +#define NEIGHBOUR_FLAGS_MASK_L2_EARTH_AND_STONES 0x2 // L2_EARTH_AND_STONES +#define NEIGHBOUR_FLAGS_MASK_L2_PLATEAU_MEDIUM 0x4 // L2_PLATEAU_MEDIUM +#define NEIGHBOUR_FLAGS_MASK_L2_PLATEAU_HIGH 0x8 // L2_PLATEAU_HIGH +#define NEIGHBOUR_FLAGS_MASK_L2_OASIS_GRASS 0x10 // L2_OASIS_GRASS +#define NEIGHBOUR_FLAGS_MASK_L2_BEACH 0x20 // L2_BEACH +#define NEIGHBOUR_FLAGS_MASK_L2_STONES 0x40 // L2_STONES_OR_DRIVEN_SANDUnk +#define NEIGHBOUR_FLAGS_MASK_L2_THICK_SCRUB 0x80 // L2_THICK_SCRUB + +#pragma optimize("", off) + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_BORDER; + using OpenSHC::Map::LogicHelpers::L_BORDER_EDGE; + using OpenSHC::Map::LogicHelpers::L_OIL; + + // FUNCTION: STRONGHOLDCRUSADER 0x004FDB00 + void TileMapState::updateMacroLayerRelated(uint logic1, uint logic2, int clearMacroFirst) + { + /* + Five copies of the same block/sub-tile loop skeleton, and eleven expansions of the + handwritten neighbour-flag macro (see NeighbourFlagsAsm.hpp). The original was built + without optimisation, so the pragma above is needed to reproduce its frame-pointer, + reload-per-access code shape; the locals are declared together, in this order, because + at /Od the stack slots are observable and MSVC assigns them per function, not per scope. + */ + int previousMacro; + int rotation; + int blockColumn; + int index; + int blockRow; + int neighbourTile; + int subRow; + int subColumn; + int tableY; + int randomValue; + int tableX; + int tileXOffset; + int savedBitFlag; + + rotation = DAT_PathFindingState::instance.mappingYRelated % 10; + for (blockRow = this->someIndex; blockRow <= this->someLimit; blockRow++) { + for (blockColumn = this->someYLike; blockColumn <= this->someYLikeLimit; blockColumn++) { + if (DAT_TileMapState::instance.mapping40x40[blockRow][blockColumn] != 0) { + subRow = rotation; + rotation = 0; + for (; subRow < 10; subRow++) { + this->DAT_SomeY = blockRow * 10 + subRow; + this->DAT_SomeX = blockColumn * 10; + for (subColumn = 0; subColumn < 10; subColumn++, this->DAT_SomeX++) { + if (MACRO_CALL_MEMBER(OpenSHC::Rendering::ViewportRenderState_Func::xyAreValid, + DAT_ViewportRenderState::ptr)(this->DAT_SomeX, this->DAT_SomeY) + != FALSE) { + this->DAT_SomeTile + = MACRO_CALL_MEMBER(OpenSHC::Rendering::ViewportRenderState_Func::translateXYToTile, + DAT_ViewportRenderState::ptr)(this->DAT_SomeX, this->DAT_SomeY); + if ((char)this->ChangedLayer[this->DAT_SomeTile] != 0) { + previousMacro = (short)this->MacroLayer[this->DAT_SomeTile]; + if (clearMacroFirst != 0) { + this->MacroLayer[this->DAT_SomeTile] = 0; + } + if ((this->LogicLayer[this->DAT_SomeTile] & logic1) != 0 + || ((char)this->Logic2Layer[this->DAT_SomeTile] & logic2) != 0) { + if ((this->LogicLayer[this->DAT_SomeTile] & (L_BORDER | L_BORDER_EDGE)) != 0) { + this->bitFlag = 0; + } else if (logic1 == 0x8000) { + MACRO_NEIGHBOUR_FLAGS_LOGIC_8(1, NEIGHBOUR_FLAGS_MASK_DEFAULT_EARTH) + } else if (logic1 == 0x20000000) { + if ((this->LogicLayer[this->DAT_SomeTile] & L_OIL) == 0) { + MACRO_NEIGHBOUR_FLAGS_LOGIC_8(2, NEIGHBOUR_FLAGS_MASK_MARSH) + if (this->bitFlag != 0xff) { + this->MacroLayer[this->DAT_SomeTile] = 1; + } else if (((short)this->RandomLayer[this->DAT_SomeTile] & 0xf) == 0) { + this->MacroLayer[this->DAT_SomeTile] = 2; + } else { + this->MacroLayer[this->DAT_SomeTile] = 0x800; + } + if (previousMacro != (short)this->MacroLayer[this->DAT_SomeTile]) { + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func:: + updateWalkAndPathLayer, + DAT_PathFindingState::ptr)(1, this->DAT_SomeX, this->DAT_SomeY); + } + } + } else if (logic2 == 0x2) { + MACRO_NEIGHBOUR_FLAGS_TERRAIN_8(3, NEIGHBOUR_FLAGS_MASK_L2_EARTH_AND_STONES) + } else if (logic2 == 0x10) { + MACRO_NEIGHBOUR_FLAGS_TERRAIN_8(4, NEIGHBOUR_FLAGS_MASK_L2_OASIS_GRASS) + } else if (logic2 == 0x1) { + MACRO_NEIGHBOUR_FLAGS_TERRAIN_8(5, NEIGHBOUR_FLAGS_MASK_L2_SCRUB) + } else if (logic2 == 0x80) { + MACRO_NEIGHBOUR_FLAGS_TERRAIN_8(6, NEIGHBOUR_FLAGS_MASK_L2_THICK_SCRUB) + } else if (logic2 == 0x40) { + MACRO_NEIGHBOUR_FLAGS_TERRAIN_8(7, NEIGHBOUR_FLAGS_MASK_L2_STONES) + } else if (logic2 == 0x20) { + MACRO_NEIGHBOUR_FLAGS_TERRAIN_8(8, NEIGHBOUR_FLAGS_MASK_L2_BEACH) + savedBitFlag = this->bitFlag; + MACRO_NEIGHBOUR_FLAGS_LOGIC_8(9, NEIGHBOUR_FLAGS_MASK_SEA) + this->bitFlag = this->bitFlag | savedBitFlag; + } else if (logic2 == 0x4) { + MACRO_NEIGHBOUR_FLAGS_TERRAIN_8(10, NEIGHBOUR_FLAGS_MASK_L2_PLATEAU_MEDIUM) + } else if (logic2 == 0x8) { + MACRO_NEIGHBOUR_FLAGS_TERRAIN_8(11, NEIGHBOUR_FLAGS_MASK_L2_PLATEAU_HIGH) + } else { + this->bitFlag = 0; + } + if (this->bitFlag != 0xff) { + this->MacroLayer[this->DAT_SomeTile] = 1; + } else if (((short)this->RandomLayer[this->DAT_SomeTile] & 0xf) == 0) { + this->MacroLayer[this->DAT_SomeTile] = 2; + } else { + this->MacroLayer[this->DAT_SomeTile] = 0x800; + } + if (previousMacro != (short)this->MacroLayer[this->DAT_SomeTile]) { + MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::PathFindingState_Func::updateWalkAndPathLayer, + DAT_PathFindingState::ptr)(1, this->DAT_SomeX, this->DAT_SomeY); + } + } + } + } + } + } + } + } + } + rotation = DAT_PathFindingState::instance.mappingYRelated % 10; + for (blockRow = this->someIndex; blockRow <= this->someLimit; blockRow++) { + for (blockColumn = this->someYLike; blockColumn <= this->someYLikeLimit; blockColumn++) { + if (DAT_TileMapState::instance.mapping40x40[blockRow][blockColumn] != 0) { + subRow = rotation; + rotation = 0; + for (; subRow < 10; subRow++) { + this->DAT_SomeY = blockRow * 10 + subRow; + this->DAT_SomeX = blockColumn * 10; + for (subColumn = 0; subColumn < 10; subColumn++, this->DAT_SomeX++) { + if (MACRO_CALL_MEMBER(OpenSHC::Rendering::ViewportRenderState_Func::xyAreValid, + DAT_ViewportRenderState::ptr)(this->DAT_SomeX, this->DAT_SomeY) + != FALSE) { + this->DAT_SomeTile + = MACRO_CALL_MEMBER(OpenSHC::Rendering::ViewportRenderState_Func::translateXYToTile, + DAT_ViewportRenderState::ptr)(this->DAT_SomeX, this->DAT_SomeY); + if ((short)this->MacroLayer[this->DAT_SomeTile] == 0x800) { + tileXOffset = MACRO_CALL_MEMBER( + OpenSHC::Rendering::ViewportRenderState_Func::computeTileXOffset, + DAT_ViewportRenderState::ptr)(this->DAT_SomeTile, this->DAT_SomeY); + randomValue = (short)this->RandomLayer[this->DAT_SomeTile] & 0xf; + for (index = 0; index < 0x10; index++) { + tableX = DAT_TerrainDefinedData::instance.MacroLayerScanOffsets[index].x; + tableY = DAT_TerrainDefinedData::instance.MacroLayerScanOffsets[index].y; + neighbourTile = MACRO_CALL_MEMBER( + OpenSHC::Rendering::ViewportRenderState_Func::translateXYToTile, + DAT_ViewportRenderState::ptr)( + tileXOffset + tableX, this->DAT_SomeY + tableY); + if ((short)this->MacroLayer[neighbourTile] != 0x800) { + break; + } + } + if (index >= 0x10) { + for (index = 0; index < 0x10; index++) { + tableX = DAT_TerrainDefinedData::instance.MacroLayerScanOffsets[index].x; + tableY = DAT_TerrainDefinedData::instance.MacroLayerScanOffsets[index].y; + neighbourTile = MACRO_CALL_MEMBER( + OpenSHC::Rendering::ViewportRenderState_Func::translateXYToTile, + DAT_ViewportRenderState::ptr)( + tileXOffset + tableX, this->DAT_SomeY + tableY); + this->MacroLayer[neighbourTile] = 0x10; + this->MacroLayer[neighbourTile] + = (short)this->MacroLayer[neighbourTile] + (short)(index << 6); + this->MacroLayer[neighbourTile] + = (short)this->MacroLayer[neighbourTile] + randomValue * 0x1000; + } + } + } + } + } + } + } + } + } + rotation = DAT_PathFindingState::instance.mappingYRelated % 10; + for (blockRow = this->someIndex; blockRow <= this->someLimit; blockRow++) { + for (blockColumn = this->someYLike; blockColumn <= this->someYLikeLimit; blockColumn++) { + if (DAT_TileMapState::instance.mapping40x40[blockRow][blockColumn] != 0) { + subRow = rotation; + rotation = 0; + for (; subRow < 10; subRow++) { + this->DAT_SomeY = blockRow * 10 + subRow; + this->DAT_SomeX = blockColumn * 10; + for (subColumn = 0; subColumn < 10; subColumn++, this->DAT_SomeX++) { + if (MACRO_CALL_MEMBER(OpenSHC::Rendering::ViewportRenderState_Func::xyAreValid, + DAT_ViewportRenderState::ptr)(this->DAT_SomeX, this->DAT_SomeY) + != FALSE) { + this->DAT_SomeTile + = MACRO_CALL_MEMBER(OpenSHC::Rendering::ViewportRenderState_Func::translateXYToTile, + DAT_ViewportRenderState::ptr)(this->DAT_SomeX, this->DAT_SomeY); + if ((short)this->MacroLayer[this->DAT_SomeTile] == 0x800) { + tileXOffset = MACRO_CALL_MEMBER( + OpenSHC::Rendering::ViewportRenderState_Func::computeTileXOffset, + DAT_ViewportRenderState::ptr)(this->DAT_SomeTile, this->DAT_SomeY); + randomValue = (short)this->RandomLayer[this->DAT_SomeTile] & 0xf; + for (index = 0; index < 9; index++) { + tableX = DAT_TerrainDefinedData::instance.field2160_0x198c[index].x; + tableY = DAT_TerrainDefinedData::instance.field2160_0x198c[index].y; + neighbourTile = MACRO_CALL_MEMBER( + OpenSHC::Rendering::ViewportRenderState_Func::translateXYToTile, + DAT_ViewportRenderState::ptr)( + tileXOffset + tableX, this->DAT_SomeY + tableY); + if ((short)this->MacroLayer[neighbourTile] != 0x800) { + break; + } + } + if (index >= 9) { + for (index = 0; index < 9; index++) { + tableX = DAT_TerrainDefinedData::instance.field2160_0x198c[index].x; + tableY = DAT_TerrainDefinedData::instance.field2160_0x198c[index].y; + neighbourTile = MACRO_CALL_MEMBER( + OpenSHC::Rendering::ViewportRenderState_Func::translateXYToTile, + DAT_ViewportRenderState::ptr)( + tileXOffset + tableX, this->DAT_SomeY + tableY); + this->MacroLayer[neighbourTile] = 8; + this->MacroLayer[neighbourTile] + = (short)this->MacroLayer[neighbourTile] + (short)(index << 6); + this->MacroLayer[neighbourTile] + = (short)this->MacroLayer[neighbourTile] + randomValue * 0x1000; + } + } + } + } + } + } + } + } + } + rotation = DAT_PathFindingState::instance.mappingYRelated % 10; + for (blockRow = this->someIndex; blockRow <= this->someLimit; blockRow++) { + for (blockColumn = this->someYLike; blockColumn <= this->someYLikeLimit; blockColumn++) { + if (DAT_TileMapState::instance.mapping40x40[blockRow][blockColumn] != 0) { + subRow = rotation; + rotation = 0; + for (; subRow < 10; subRow++) { + this->DAT_SomeY = blockRow * 10 + subRow; + this->DAT_SomeX = blockColumn * 10; + for (subColumn = 0; subColumn < 10; subColumn++, this->DAT_SomeX++) { + if (MACRO_CALL_MEMBER(OpenSHC::Rendering::ViewportRenderState_Func::xyAreValid, + DAT_ViewportRenderState::ptr)(this->DAT_SomeX, this->DAT_SomeY) + != FALSE) { + this->DAT_SomeTile + = MACRO_CALL_MEMBER(OpenSHC::Rendering::ViewportRenderState_Func::translateXYToTile, + DAT_ViewportRenderState::ptr)(this->DAT_SomeX, this->DAT_SomeY); + if ((short)this->MacroLayer[this->DAT_SomeTile] == 0x800) { + tileXOffset = MACRO_CALL_MEMBER( + OpenSHC::Rendering::ViewportRenderState_Func::computeTileXOffset, + DAT_ViewportRenderState::ptr)(this->DAT_SomeTile, this->DAT_SomeY); + randomValue = (short)this->RandomLayer[this->DAT_SomeTile] & 0xf; + for (index = 0; index < 4; index++) { + tableX = DAT_TerrainDefinedData::instance.field2159_0x196c[index].x; + tableY = DAT_TerrainDefinedData::instance.field2159_0x196c[index].y; + neighbourTile = MACRO_CALL_MEMBER( + OpenSHC::Rendering::ViewportRenderState_Func::translateXYToTile, + DAT_ViewportRenderState::ptr)( + tileXOffset + tableX, this->DAT_SomeY + tableY); + if ((short)this->MacroLayer[neighbourTile] != 0x800) { + break; + } + } + if (index >= 4) { + for (index = 0; index < 4; index++) { + tableX = DAT_TerrainDefinedData::instance.field2159_0x196c[index].x; + tableY = DAT_TerrainDefinedData::instance.field2159_0x196c[index].y; + neighbourTile = MACRO_CALL_MEMBER( + OpenSHC::Rendering::ViewportRenderState_Func::translateXYToTile, + DAT_ViewportRenderState::ptr)( + tileXOffset + tableX, this->DAT_SomeY + tableY); + this->MacroLayer[neighbourTile] = 4; + this->MacroLayer[neighbourTile] + = (short)this->MacroLayer[neighbourTile] + (short)(index << 6); + this->MacroLayer[neighbourTile] + = (short)this->MacroLayer[neighbourTile] + randomValue * 0x1000; + } + } + } + } + } + } + } + } + } + rotation = DAT_PathFindingState::instance.mappingYRelated % 10; + for (blockRow = this->someIndex; blockRow <= this->someLimit; blockRow++) { + for (blockColumn = this->someYLike; blockColumn <= this->someYLikeLimit; blockColumn++) { + if (DAT_TileMapState::instance.mapping40x40[blockRow][blockColumn] != 0) { + subRow = rotation; + rotation = 0; + for (; subRow < 10; subRow++) { + this->DAT_SomeY = blockRow * 10 + subRow; + this->DAT_SomeX = blockColumn * 10; + for (subColumn = 0; subColumn < 10; subColumn++, this->DAT_SomeX++) { + if (MACRO_CALL_MEMBER(OpenSHC::Rendering::ViewportRenderState_Func::xyAreValid, + DAT_ViewportRenderState::ptr)(this->DAT_SomeX, this->DAT_SomeY) + != FALSE) { + this->DAT_SomeTile + = MACRO_CALL_MEMBER(OpenSHC::Rendering::ViewportRenderState_Func::translateXYToTile, + DAT_ViewportRenderState::ptr)(this->DAT_SomeX, this->DAT_SomeY); + if ((short)this->MacroLayer[this->DAT_SomeTile] == 0x800) { + this->MacroLayer[this->DAT_SomeTile] = 2; + } + } + } + } + } + } + } + } + +} +} + +#pragma optimize("", on) diff --git a/src/OpenSHC/Map/TileMapState/updateMacroLayerRelated2.cpp b/src/OpenSHC/Map/TileMapState/updateMacroLayerRelated2.cpp new file mode 100644 index 0000000000..393ae7b6b1 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/updateMacroLayerRelated2.cpp @@ -0,0 +1,262 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Globals/DAT_PathFindingState.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_SEA; + + // FUNCTION: STRONGHOLDCRUSADER 0x004FF080 + void TileMapState::updateMacroLayerRelated2() + { + int startRow; + startRow = DAT_PathFindingState::instance.mappingYRelated % 10; + for (int block = this->someIndex; block <= this->someLimit; block++) { + for (int sub = this->someYLike; sub <= this->someYLikeLimit; sub++) { + if (this->mapping40x40[block][sub] == 0) { + continue; + } + for (int row = startRow; row < 10; row++) { + this->DAT_SomeY = block * 10 + row; + this->DAT_SomeX = sub * 10; + int group = 2; + do { + if ((uint)this->DAT_SomeX < 400 && (uint)this->DAT_SomeY < 400 + && DAT_ViewportRenderState::instance + .DAT_BinaryTileMap400x400[this->DAT_SomeY * 400 + this->DAT_SomeX] + != 0) { + this->DAT_SomeTile + = DAT_ViewportRenderState::instance.translationMatrix[this->DAT_SomeY].addXgetTile + + this->DAT_SomeX; + if (this->ChangedLayer[this->DAT_SomeTile] != 0 + && (this->LogicLayer[this->DAT_SomeTile] & L_SEA) != 0) { + this->MacroLayer[this->DAT_SomeTile] = 0x800; + } + } + { + uint nextX = this->DAT_SomeX + 1; + if (nextX < 400 && (uint)this->DAT_SomeY < 400 + && DAT_ViewportRenderState::instance + .DAT_BinaryTileMap400x400[this->DAT_SomeY * 400 + nextX] + != 0) { + this->DAT_SomeTile + = DAT_ViewportRenderState::instance.translationMatrix[this->DAT_SomeY].addXgetTile + + nextX; + if (this->ChangedLayer[this->DAT_SomeTile] != 0 + && (this->LogicLayer[this->DAT_SomeTile] & L_SEA) != 0) { + this->MacroLayer[this->DAT_SomeTile] = 0x800; + } + } + this->DAT_SomeX = nextX; + } + { + uint nextX = this->DAT_SomeX + 1; + if (nextX < 400 && (uint)this->DAT_SomeY < 400 + && DAT_ViewportRenderState::instance + .DAT_BinaryTileMap400x400[this->DAT_SomeY * 400 + nextX] + != 0) { + this->DAT_SomeTile + = DAT_ViewportRenderState::instance.translationMatrix[this->DAT_SomeY].addXgetTile + + nextX; + if (this->ChangedLayer[this->DAT_SomeTile] != 0 + && (this->LogicLayer[this->DAT_SomeTile] & L_SEA) != 0) { + this->MacroLayer[this->DAT_SomeTile] = 0x800; + } + } + this->DAT_SomeX = nextX; + } + { + uint nextX = this->DAT_SomeX + 1; + if (nextX < 400 && (uint)this->DAT_SomeY < 400 + && DAT_ViewportRenderState::instance + .DAT_BinaryTileMap400x400[this->DAT_SomeY * 400 + nextX] + != 0) { + this->DAT_SomeTile + = DAT_ViewportRenderState::instance.translationMatrix[this->DAT_SomeY].addXgetTile + + nextX; + if (this->ChangedLayer[this->DAT_SomeTile] != 0 + && (this->LogicLayer[this->DAT_SomeTile] & L_SEA) != 0) { + this->MacroLayer[this->DAT_SomeTile] = 0x800; + } + } + this->DAT_SomeX = nextX; + } + { + uint nextX = this->DAT_SomeX + 1; + if (nextX < 400 && (uint)this->DAT_SomeY < 400 + && DAT_ViewportRenderState::instance + .DAT_BinaryTileMap400x400[this->DAT_SomeY * 400 + nextX] + != 0) { + this->DAT_SomeTile + = DAT_ViewportRenderState::instance.translationMatrix[this->DAT_SomeY].addXgetTile + + nextX; + if (this->ChangedLayer[this->DAT_SomeTile] != 0 + && (this->LogicLayer[this->DAT_SomeTile] & L_SEA) != 0) { + this->MacroLayer[this->DAT_SomeTile] = 0x800; + } + } + this->DAT_SomeX = nextX; + } + this->DAT_SomeX = this->DAT_SomeX + 1; + group = group - 1; + } while (group != 0); + } + startRow = 0; + } + } + + startRow = DAT_PathFindingState::instance.mappingYRelated % 10; + for (int block = this->someIndex; block <= this->someLimit; block++) { + for (int sub = this->someYLike; sub <= this->someYLikeLimit; sub++) { + if (this->mapping40x40[block][sub] == 0) { + continue; + } + for (int row = startRow; row < 10; row++) { + this->DAT_SomeY = block * 10 + row; + this->DAT_SomeX = sub * 10; + int column = 10; + do { + if ((uint)this->DAT_SomeX < 400 && (uint)this->DAT_SomeY < 400 + && DAT_ViewportRenderState::instance + .DAT_BinaryTileMap400x400[this->DAT_SomeY * 400 + this->DAT_SomeX] + != 0) { + this->DAT_SomeTile = this->DAT_SomeX + + DAT_ViewportRenderState::instance.translationMatrix[this->DAT_SomeY].addXgetTile; + if (this->MacroLayer[this->DAT_SomeTile] == 0x800 + && (this->LogicLayer[this->DAT_SomeTile] & L_SEA) != 0) { + ushort random = this->RandomLayer[this->DAT_SomeTile]; + int corner = this->DAT_SomeTile + - DAT_ViewportRenderState::instance.translationMatrix[this->DAT_SomeY].addXgetTile; + /* a wave sprite only fits where all sixteen of its tiles are still marked */ + bool complete = true; + for (int i = 0; i < 0x10; i++) { + if (this->MacroLayer[DAT_ViewportRenderState::instance + .translationMatrix[DAT_TerrainDefinedData::instance + .MacroLayerScanOffsets[i] + .y + + this->DAT_SomeY] + .addXgetTile + + DAT_TerrainDefinedData::instance.MacroLayerScanOffsets[i].x + corner] + != 0x800) { + complete = false; + break; + } + } + if (complete) { + for (int i = 0; i < 0x10; i++) { + this->MacroLayer[DAT_ViewportRenderState::instance + .translationMatrix[DAT_TerrainDefinedData::instance + .MacroLayerScanOffsets[i] + .y + + this->DAT_SomeY] + .addXgetTile + + DAT_TerrainDefinedData::instance.MacroLayerScanOffsets[i].x + corner] + = (ushort)(byte)random * 0x1000 + 0x10 + (short)(i << 6); + } + } + } + } + this->DAT_SomeX = this->DAT_SomeX + 1; + column = column - 1; + } while (column != 0); + } + startRow = 0; + } + } + + startRow = DAT_PathFindingState::instance.mappingYRelated % 10; + for (int block = this->someIndex; block <= this->someLimit; block++) { + for (int sub = this->someYLike; sub <= this->someYLikeLimit; sub++) { + if (this->mapping40x40[block][sub] == 0) { + continue; + } + for (int row = startRow; row < 10; row++) { + this->DAT_SomeY = block * 10 + row; + this->DAT_SomeX = sub * 10; + int group = 2; + do { + if ((uint)this->DAT_SomeX < 400 && (uint)this->DAT_SomeY < 400 + && DAT_ViewportRenderState::instance + .DAT_BinaryTileMap400x400[this->DAT_SomeY * 400 + this->DAT_SomeX] + != 0) { + this->DAT_SomeTile + = DAT_ViewportRenderState::instance.translationMatrix[this->DAT_SomeY].addXgetTile + + this->DAT_SomeX; + if (this->MacroLayer[this->DAT_SomeTile] == 0x800) { + this->MacroLayer[this->DAT_SomeTile] = 2; + } + } + { + uint nextX = this->DAT_SomeX + 1; + if (nextX < 400 && (uint)this->DAT_SomeY < 400 + && DAT_ViewportRenderState::instance + .DAT_BinaryTileMap400x400[this->DAT_SomeY * 400 + nextX] + != 0) { + this->DAT_SomeTile + = DAT_ViewportRenderState::instance.translationMatrix[this->DAT_SomeY].addXgetTile + + nextX; + if (this->MacroLayer[this->DAT_SomeTile] == 0x800) { + this->MacroLayer[this->DAT_SomeTile] = 2; + } + } + this->DAT_SomeX = nextX; + } + { + uint nextX = this->DAT_SomeX + 1; + if (nextX < 400 && (uint)this->DAT_SomeY < 400 + && DAT_ViewportRenderState::instance + .DAT_BinaryTileMap400x400[this->DAT_SomeY * 400 + nextX] + != 0) { + this->DAT_SomeTile + = DAT_ViewportRenderState::instance.translationMatrix[this->DAT_SomeY].addXgetTile + + nextX; + if (this->MacroLayer[this->DAT_SomeTile] == 0x800) { + this->MacroLayer[this->DAT_SomeTile] = 2; + } + } + this->DAT_SomeX = nextX; + } + { + uint nextX = this->DAT_SomeX + 1; + if (nextX < 400 && (uint)this->DAT_SomeY < 400 + && DAT_ViewportRenderState::instance + .DAT_BinaryTileMap400x400[this->DAT_SomeY * 400 + nextX] + != 0) { + this->DAT_SomeTile + = DAT_ViewportRenderState::instance.translationMatrix[this->DAT_SomeY].addXgetTile + + nextX; + if (this->MacroLayer[this->DAT_SomeTile] == 0x800) { + this->MacroLayer[this->DAT_SomeTile] = 2; + } + } + this->DAT_SomeX = nextX; + } + { + uint nextX = this->DAT_SomeX + 1; + if (nextX < 400 && (uint)this->DAT_SomeY < 400 + && DAT_ViewportRenderState::instance + .DAT_BinaryTileMap400x400[this->DAT_SomeY * 400 + nextX] + != 0) { + this->DAT_SomeTile + = DAT_ViewportRenderState::instance.translationMatrix[this->DAT_SomeY].addXgetTile + + nextX; + if (this->MacroLayer[this->DAT_SomeTile] == 0x800) { + this->MacroLayer[this->DAT_SomeTile] = 2; + } + } + this->DAT_SomeX = nextX; + } + this->DAT_SomeX = this->DAT_SomeX + 1; + group = group - 1; + } while (group != 0); + } + startRow = 0; + } + } + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/updatePathLinkagesForBuilding.cpp b/src/OpenSHC/Map/TileMapState/updatePathLinkagesForBuilding.cpp new file mode 100644 index 0000000000..a90edaa412 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/updatePathLinkagesForBuilding.cpp @@ -0,0 +1,76 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" +#include "OpenSHC/Map/Buildings/BuildingType.hpp" + +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_PathFindingState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::Buildings::BuildingType; + + // FUNCTION: STRONGHOLDCRUSADER 0x00506AD0 + void TileMapState::updatePathLinkagesForBuilding(int buildingID) + { + int buildingSizeTileIndex = 0; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)( + buildingSizeTileIndex, DAT_BuildingsState::instance.buildings[buildingID].widthOrHeight); + int tileUnk = DAT_ViewportRenderState::instance + .translationMatrix[DAT_BuildingsState::instance.buildings[buildingID].y + this->buildingY] + .addXgetTile + + DAT_BuildingsState::instance.buildings[buildingID].x + this->buildingX; + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::updatePathLinkagesInAllEightDirections, + DAT_PathFindingState::ptr)(DAT_BuildingsState::instance.buildings[buildingID].y + this->buildingY, tileUnk); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::clearMoat, this)(tileUnk); + buildingSizeTileIndex++; + } while (buildingSizeTileIndex < this->constructionTileCount); + + short buildingType = DAT_BuildingsState::instance.buildings[buildingID].buildingType; + if (buildingType == OpenSHC::Map::Buildings::BT_GATEHOUSELARGE) { + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::updatePathLinkageTileMapRelatedToGates, + DAT_PathFindingState::ptr)(buildingID); + return; + } + if (buildingType == OpenSHC::Map::Buildings::BT_GATEHOUSESMALL) { + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::updatePathLinkageTileMapRelatedToGates, + DAT_PathFindingState::ptr)(buildingID); + return; + } + if (buildingType == OpenSHC::Map::Buildings::BT_WOODGATE1) { + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::updatePathLinkageTileMapRelatedToGates, + DAT_PathFindingState::ptr)(buildingID); + return; + } + if (buildingType == OpenSHC::Map::Buildings::BT_STONEKEEP) { + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::updatePathLinkageTileMapRelatedToKeeps, + DAT_PathFindingState::ptr)(buildingID); + return; + } + if (buildingType == OpenSHC::Map::Buildings::BT_STRONGHOLD) { + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::updatePathLinkageTileMapRelatedToKeeps, + DAT_PathFindingState::ptr)(buildingID); + return; + } + if (buildingType == OpenSHC::Map::Buildings::BT_KEEPFOUR) { + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::updatePathLinkageTileMapRelatedToKeeps, + DAT_PathFindingState::ptr)(buildingID); + return; + } + if (buildingType == OpenSHC::Map::Buildings::BT_KEEPFIVE) { + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::updatePathLinkageTileMapRelatedToKeeps, + DAT_PathFindingState::ptr)(buildingID); + return; + } + if (buildingType == OpenSHC::Map::Buildings::BT_SIEGETOWER_PLACED) { + MACRO_CALL_MEMBER( + OpenSHC::Map::Navigation::PathFindingState_Func::updatePathLinkageTileMapRelatedToSiegeTower, + DAT_PathFindingState::ptr)(buildingID); + } + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/updatePitchDitches.cpp b/src/OpenSHC/Map/TileMapState/updatePitchDitches.cpp new file mode 100644 index 0000000000..40ad29f70a --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/updatePitchDitches.cpp @@ -0,0 +1,78 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Map/Entities.func.hpp" + +#include "OpenSHC/Globals/DAT_GameState.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_TileMapState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_PLAIN2_AND_PITCH; + + // FUNCTION: STRONGHOLDCRUSADER 0x005114C0 + void TileMapState::updatePitchDitches() + { + if (DAT_GameState::instance.gameTicksLoadBalancer % 10 == 3) { + this->maxPitchDitchCount = 0; + for (int id = 1; id < 4000; id++) { + if (this->pitchDitches[id].owner != 0) { + this->maxPitchDitchCount = id + 1; + } + } + } + + for (int id = 1; id < this->maxPitchDitchCount; id++) { + if (this->pitchDitches[id].owner == 0) { + continue; + } + int tile = this->pitchDitches[id].tile; + if ((this->LogicLayer[tile] & L_PLAIN2_AND_PITCH) == 0 || this->pitchDitches[id].state == -1) { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::destroyPitchDitch, this)(id); + } else if (this->pitchDitches[id].state == 0) { + /* the original increments the state rather than storing the literal */ + this->pitchDitches[id].state = this->pitchDitches[id].state + 1; + this->pitchDitches[id].field7_0x12 = 0; + } else if (this->pitchDitches[id].state == 2) { + this->pitchDitches[id].field7_0x12 = this->pitchDitches[id].field7_0x12 + 1; + if (this->pitchDitches[id].field7_0x12 == 20) { + this->pitchDitches[id].state = this->pitchDitches[id].state + 1; + this->pitchDitches[id].field7_0x12 = 0; + uint height = DAT_TileMapState::instance.HeightLayer[tile]; + /* the fire spreads to the four adjacent ditches that are still unlit */ + for (int i = 0; i < 4; i++) { + int neighbour = DAT_ViewportRenderState::instance + .translationMatrix[this->pitchDitches[id].y + + DAT_TerrainDefinedData::instance.field2346_0x376c[i].y] + .addXgetTile + + this->pitchDitches[id].x + DAT_TerrainDefinedData::instance.field2346_0x376c[i].x; + if ((this->LogicLayer[neighbour] & L_PLAIN2_AND_PITCH) == 0) { + continue; + } + int other = MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getPitchDitchIDForTile, this)( + neighbour); + if (other == 0 || this->pitchDitches[other].state != 1) { + continue; + } + if (abs((int)(height - DAT_TileMapState::instance.HeightLayer[neighbour])) < 25) { + MACRO_CALL(OpenSHC::Map::Entities_Func::SetPlaceOnFire)(this->pitchDitches[other].owner, + this->pitchDitches[other].x * 8, this->pitchDitches[other].y * 8, + DAT_TileMapState::instance.HeightLayer[this->pitchDitches[other].tile], 3); + this->pitchDitches[other].state = 2; + } + } + } + } else if (this->pitchDitches[id].state == 3) { + this->pitchDitches[id].field7_0x12 = this->pitchDitches[id].field7_0x12 + 1; + if (this->pitchDitches[id].field7_0x12 == 200) { + DAT_TileMapState::instance.HeightLayer[tile] = DAT_TileMapState::instance.DefaultHeightLayer[tile]; + this->pitchDitches[id].state = -1; + } + } + } + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/updateShowHiLayerOrResetChangedLayer.cpp b/src/OpenSHC/Map/TileMapState/updateShowHiLayerOrResetChangedLayer.cpp new file mode 100644 index 0000000000..2df718ed05 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/updateShowHiLayerOrResetChangedLayer.cpp @@ -0,0 +1,87 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Globals/DAT_RotateMapOrPullDownTerrain.hpp" + +namespace OpenSHC { +namespace Map { + + // FUNCTION: STRONGHOLDCRUSADER 0x00501A20 + void TileMapState::updateShowHiLayerOrResetChangedLayer() + { + int importHeight = 0; + this->refreshRelatedTwo = 0; + if (this->refreshCertainTileMap == 0) { + return; + } + + this->counter1 = this->counter1 + 1; + this->refreshCertainTileMap_old = this->refreshCertainTileMap; + this->refreshRelatedOne = 0; + for (int row = 0; row < 256; row++) { + int target = ((uint)row >> 2) + 1; + /* the pull-down eases towards the target in steps that shrink as it gets closer */ + int step; + if (this->refreshCertainTileMap == 3) { + step = this->heightBasedScreenYOffset[row] - target; + } else if (this->refreshCertainTileMap == 4) { + step = row - this->heightBasedScreenYOffset[row]; + } else { + step = 0; + } + if (step > 60) { + step = 30; + } else if (step > 40) { + step = 20; + } else if (step > 30) { + step = 14; + } else if (step > 20) { + step = 8; + } else if (step > 10) { + step = 4; + } else if (step > 6) { + step = 3; + } else if (step > 2) { + step = 2; + } else if (step > 0) { + step = 1; + } else { + step = 0; + } + + if (this->refreshCertainTileMap == 1) { + this->heightBasedScreenYOffset[row] = target; + } else if (this->refreshCertainTileMap == 2) { + this->heightBasedScreenYOffset[row] = row; + } else if (this->refreshCertainTileMap == 3) { + this->heightBasedScreenYOffset[row] = this->heightBasedScreenYOffset[row] - step; + if (this->heightBasedScreenYOffset[row] > target) { + importHeight = 1; + } + } else if (this->refreshCertainTileMap == 4) { + this->heightBasedScreenYOffset[row] = this->heightBasedScreenYOffset[row] + step; + if (this->heightBasedScreenYOffset[row] != row) { + importHeight = 1; + } + } + } + + this->refreshRelatedTwo = 1; + if (importHeight != 0) { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::rebuildShowHiLayerFromHeights, this)(); + return; + } + if (this->refreshCertainTileMap == 4 || this->refreshCertainTileMap == 2) { + this->refreshRelatedOne = 1; + } else { + this->refreshRelatedOne = 0; + this->refreshRelatedTwo = 2; + } + this->refreshCertainTileMap = 0; + this->forceUpdateLogicalAndMiscDisplayLayers = 1; + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::setChangedLayerToThreeAndMapping0x40x40, this)(); + this->counter1 = 0; + DAT_RotateMapOrPullDownTerrain::instance = 1; + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/upgradeMapFormatLogicLayer.cpp b/src/OpenSHC/Map/TileMapState/upgradeMapFormatLogicLayer.cpp new file mode 100644 index 0000000000..37848d246b --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/upgradeMapFormatLogicLayer.cpp @@ -0,0 +1,44 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Map/MapConstants.hpp" +#include "OpenSHC/Map/Version.func.hpp" + +namespace OpenSHC { +namespace Map { + + // FUNCTION: STRONGHOLDCRUSADER 0x00511D70 + void TileMapState::upgradeMapFormatLogicLayer( + PackagedFileMagicNum receivedMapVersion, PackagedFileMagicNum packagerMapVersion) + { + MACRO_CALL(OpenSHC::Map::Version_Func::UpgradeMapLogicToVersion_Unknown1)(); + MACRO_CALL(OpenSHC::Map::Version_Func::UpgradeMapLogicToVersion_Unknown2)(); + MACRO_CALL(OpenSHC::Map::Version_Func::UpgradeMapLogicToVersion_Unknown3)(); + if (this->mapSize == 0) { + this->mapSize = MC_MAP_XY_LIMIT; + } + if (receivedMapVersion == packagerMapVersion) { + return; + } + + if ((int)receivedMapVersion < 102) { + MACRO_CALL(OpenSHC::Map::Version_Func::UpgradeMapLogicToVersion_102)(); + } + if ((int)receivedMapVersion < 120) { + MACRO_CALL(OpenSHC::Map::Version_Func::UpgradeMapLogicToVersion_120)(); + } + if ((int)receivedMapVersion < 125) { + MACRO_CALL(OpenSHC::Map::Version_Func::UpgradeMapLogicToVersion_125)(); + } + if ((int)receivedMapVersion < 128) { + MACRO_CALL(OpenSHC::Map::Version_Func::UpgradeMapLogicToVersion_128)(); + } + if ((int)receivedMapVersion < 145) { + MACRO_CALL(OpenSHC::Map::Version_Func::UpgradeMapLogicToVersion_145)(); + } + if ((int)receivedMapVersion < 147) { + MACRO_CALL(OpenSHC::Map::Version_Func::UpgradeMapLogicToVersion_147)(); + } + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/upgradeTowerLogicLayer.cpp b/src/OpenSHC/Map/TileMapState/upgradeTowerLogicLayer.cpp new file mode 100644 index 0000000000..c443886a27 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/upgradeTowerLogicLayer.cpp @@ -0,0 +1,51 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_BUILDING; + using OpenSHC::Map::LogicHelpers::L_KEEP_NON_MANOR_HOUSE; + + using OpenSHC::Map::LogicHelpers::L_BUILDING; + using OpenSHC::Map::LogicHelpers::L_KEEP_NON_MANOR_HOUSE; + + // FUNCTION: STRONGHOLDCRUSADER 0x00507280 + void TileMapState::upgradeTowerLogicLayer(int buildingID) + { + int buildingSizeTileIndex = 0; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getBuildingSizeIndexMappingData, this)( + buildingSizeTileIndex, DAT_BuildingsState::instance.buildings[buildingID].widthOrHeight); + int tile = DAT_ViewportRenderState::instance + .translationMatrix[DAT_BuildingsState::instance.buildings[buildingID].y + this->buildingY] + .addXgetTile + + DAT_BuildingsState::instance.buildings[buildingID].x + this->buildingX; + this->LogicLayer[tile] = this->LogicLayer[tile] & ~L_BUILDING; + uint widthOrHeight = DAT_BuildingsState::instance.buildings[buildingID].widthOrHeight; + uint logic = this->LogicLayer[tile]; + if (DAT_TerrainDefinedData::instance.TowerTileOffsetsBySize[widthOrHeight][0] == buildingSizeTileIndex) { + logic = logic | L_BUILDING; + } else if (DAT_TerrainDefinedData::instance.TowerTileOffsetsBySize[widthOrHeight][1] + == buildingSizeTileIndex) { + logic = logic | L_BUILDING; + } else if (DAT_TerrainDefinedData::instance.TowerTileOffsetsBySize[widthOrHeight][2] + == buildingSizeTileIndex) { + logic = logic | L_BUILDING; + } else if (DAT_TerrainDefinedData::instance.TowerTileOffsetsBySize[widthOrHeight][3] + == buildingSizeTileIndex) { + logic = logic | L_BUILDING; + } else { + logic = logic | L_KEEP_NON_MANOR_HOUSE; + } + buildingSizeTileIndex++; + this->LogicLayer[tile] = logic; + } while (buildingSizeTileIndex < this->constructionTileCount); + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::updatePathLinkagesForBuilding, this)(buildingID); + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/useEraserBrush.cpp b/src/OpenSHC/Map/TileMapState/useEraserBrush.cpp new file mode 100644 index 0000000000..5d9402091f --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/useEraserBrush.cpp @@ -0,0 +1,121 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Map/Buildings/BuildingsState.func.hpp" +#include "OpenSHC/Map/Entities/EntityState.func.hpp" +#include "OpenSHC/Map/LandscapeState.func.hpp" +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" +#include "OpenSHC/Map/Buildings/BuildingType.hpp" +#include "OpenSHC/Map/Units/UnitLogicState.hpp" +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_EntityState.hpp" +#include "OpenSHC/Globals/DAT_GameState.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_UnitsState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::Buildings::BuildingType; + using OpenSHC::Map::Units::UnitLogicState; + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x005017C0 + void TileMapState::useEraserBrush(uint x, uint y, int brush) + { + uint baseY = y; + uint baseX = x; + brush = DAT_TerrainDefinedData::instance.BrushSizeArray[brush]; + int baseTile = DAT_ViewportRenderState::instance.translationMatrix[y].addXgetTile + x; + /* the original reuses the x parameter as the tile the brush is walking */ + x = baseTile; + MACRO_CALL_MEMBER(OpenSHC::Map::Entities::EntityState_Func::destroyEntitiesOnTile, DAT_EntityState::ptr)( + baseTile); + + if (brush > 0) { + int index = 0; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getTileForBrush, this)( + 1, index, (int*)&x, (int*)&y, baseTile, baseY); + int organism = (short)this->OrganismLayer[x]; + if (organism != 0) { + /* tree ids come first, rock ids are biased by 2000 */ + if (organism >= 2000) { + MACRO_CALL_MEMBER(OpenSHC::Map::LandscapeState_Func::removeRock, DAT_LandscapeState::ptr)( + organism - 2000); + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::updateWalkAndPathLayer, + DAT_PathFindingState::ptr)(8, baseX, y); + } else { + MACRO_CALL_MEMBER(OpenSHC::Map::LandscapeState_Func::removeTree, DAT_LandscapeState::ptr)( + organism); + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::updateWalkAndPathLayer, + DAT_PathFindingState::ptr)(3, baseX, y); + } + DAT_PathFindingState::instance.toggleUpdateSeparateAreaTileMap = 1; + } + index++; + } while (index < brush); + } + + y = baseY; + if (brush > 0) { + int index = 0; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getTileForBrush, this)( + 1, index, (int*)&x, (int*)&y, baseTile, baseY); + this->placementOnWall = 0; + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::validateBuildingPlacementAtTile, this)(0, baseX, y); + if (this->buildingPlacementFail == FALSE) { + if (this->placementOnWall != 0) { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::spawnEraserTileEffect, this)( + 0, DAT_ViewportRenderState::instance.translationMatrix[y].addXgetTile + baseX); + } else if (this->cursorTargetID != 0xffffffff) { + /* razing a keep takes the stockpile with it, and the other way round */ + short owner = DAT_BuildingsState::instance.buildings[this->cursorTargetID].owner; + if (this->cursorTargetID == DAT_GameState::instance.playerDataArray[owner].keep.id + && DAT_GameState::instance.playerDataArray[owner].stockpile.id != 0) { + this->showNoRubbleWhenDestroyingBuilding = 1; + MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::destroyBuildingAndLinkedDuplicates, + DAT_BuildingsState::ptr)(DAT_GameState::instance.playerDataArray[owner].stockpile.id); + } + if (DAT_BuildingsState::instance.buildings[this->cursorTargetID].buildingType + == OpenSHC::Map::Buildings::BT_STOCKPILE + && DAT_GameState::instance.playerDataArray[owner].keep.id != 0) { + this->showNoRubbleWhenDestroyingBuilding = 1; + MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::destroyBuildingAndLinkedDuplicates, + DAT_BuildingsState::ptr)(DAT_GameState::instance.playerDataArray[owner].keep.id); + } + this->showNoRubbleWhenDestroyingBuilding = 1; + MACRO_CALL_MEMBER( + OpenSHC::Map::Buildings::BuildingsState_Func::destroyBuildingAndLinkedDuplicates, + DAT_BuildingsState::ptr)(this->cursorTargetID); + } + } + index++; + } while (index < brush); + } + + y = baseY; + if (brush > 0) { + int index = 0; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getTileForBrush, this)( + 1, index, (int*)&x, (int*)&y, baseTile, baseY); + for (int unit = (short)DAT_TileMapState::instance.UnitLayer[x]; unit != 0; + unit = DAT_UnitsState::instance.units[unit].nextUnitOnTheSameTile) { + DAT_UnitsState::instance.units[unit].logicalState = OpenSHC::Map::Units::ULS_REMOVE; + } + index++; + } while (index < brush); + } + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/useLevelBrush.cpp b/src/OpenSHC/Map/TileMapState/useLevelBrush.cpp new file mode 100644 index 0000000000..c03f3ad7a5 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/useLevelBrush.cpp @@ -0,0 +1,115 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" +#include "OpenSHC/Map/TileMapState/NeighbourFlagsAsm.hpp" + +#include "OpenSHC/Globals/DAT_PathFindingState.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_BORDER; + using OpenSHC::Map::LogicHelpers::L_BORDER_EDGE; + using OpenSHC::Map::LogicHelpers::L_BUILDING; + using OpenSHC::Map::LogicHelpers::L_KEEP_NON_MANOR_HOUSE; + using OpenSHC::Map::LogicHelpers::L_MARSH; + using OpenSHC::Map::LogicHelpers::L_MOAT; + using OpenSHC::Map::LogicHelpers::L_MOAT_DUG_OR_PLANNED; + using OpenSHC::Map::LogicHelpers::L_RIVER; + using OpenSHC::Map::LogicHelpers::L_ROCKY; + using OpenSHC::Map::LogicHelpers::L_SEA; + using OpenSHC::Map::LogicHelpers::L_WALL_OR_GATEHOUSE; + + // FUNCTION: STRONGHOLDCRUSADER 0x00502110 + void TileMapState::useLevelBrush(int tile, uint y, uint brush, int param_4) + { + int baseTile = tile; + uint baseY = y; + int brushSize = DAT_TerrainDefinedData::instance.BrushSizeArray[brush]; + + int highest = 0; + /* the original reuses the brush parameter to hold the lowest height seen */ + brush = 200; + for (int index = 0; index < brushSize; index++) { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getTileForBrush, this)( + 1, index, &tile, (int*)&y, baseTile, baseY); + if ((this->LogicLayer[tile] & (L_BORDER | L_BORDER_EDGE)) == 0) { + int height = this->HeightLayer[tile]; + if (height > highest) { + highest = height; + } + if (height < (int)brush) { + brush = height; + } + } + } + + int average = (int)(brush + highest) / 2; + tile = baseTile; + y = baseY; + for (int index = 0; index < brushSize; index++) { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getTileForBrush, this)( + 1, index, &tile, (int*)&y, baseTile, baseY); + int brushTile = tile; + uint logic = this->LogicLayer[brushTile]; + if ((logic & (L_BORDER | L_BORDER_EDGE)) != 0) { + continue; + } + if ((logic & (L_SEA | L_MARSH)) != 0 && this->editorAffectType == 0) { + continue; + } + if ((logic & (L_SEA | L_MARSH)) == 0 && this->editorAffectType == 1) { + continue; + } + if ((logic & (L_WALL_OR_GATEHOUSE | L_BUILDING | L_MOAT_DUG_OR_PLANNED | L_KEEP_NON_MANOR_HOUSE | L_MOAT)) + != 0) { + continue; + } + if (this->BuildingLayer[brushTile] != 0 || (logic & L_SEA) != 0) { + continue; + } + + if ((logic & L_RIVER) != 0) { + this->HeightLayer[brushTile] = this->HeightLayer[brushTile] + 8; + } + this->LogicLayer[brushTile] = this->LogicLayer[brushTile] & ~L_ROCKY; + /* the tile moves a tenth of the way towards the brush average, plus one */ + byte levelled; + bool levelChanged = true; + if ((int)(uint)this->HeightLayer[brushTile] < average) { + levelled = (char)((average - (int)(uint)this->HeightLayer[brushTile]) / 10) + + this->HeightLayer[brushTile] + 1; + } else if ((int)(uint)this->HeightLayer[brushTile] > average) { + levelled = this->HeightLayer[brushTile] + - (char)(((int)(uint)this->HeightLayer[brushTile] - average) / 10) - 1; + } else { + levelChanged = false; + } + if (levelChanged) { + this->HeightLayer[brushTile] = levelled; + this->Logic2Layer[brushTile] = 0; + } + if (this->HeightLayer[brushTile] < 8) { + this->HeightLayer[brushTile] = 8; + } + if (this->HeightLayer[brushTile] > 0x9c) { + this->HeightLayer[brushTile] = 0x9c; + } + this->DefaultHeightLayer[brushTile] = this->HeightLayer[brushTile]; + if ((this->LogicLayer[brushTile] & L_RIVER) != 0) { + this->HeightLayer[brushTile] = this->HeightLayer[brushTile] - 8; + } + uint brushY = y; + this->DAT_SomeTile = brushTile; + this->DAT_SomeY = brushY; + + /* handwritten assembly in the original: mark this tile and its eight neighbours changed */ + MACRO_MARK_CHANGED_NEIGHBOURS() + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::updatePathLinkagesInAllEightDirections, + DAT_PathFindingState::ptr)(brushY, brushTile); + } + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/useTerrainHeightBrush.cpp b/src/OpenSHC/Map/TileMapState/useTerrainHeightBrush.cpp new file mode 100644 index 0000000000..a2d4120d42 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/useTerrainHeightBrush.cpp @@ -0,0 +1,129 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Map/LandscapeState.func.hpp" +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" +#include "OpenSHC/Map/TileMapState/NeighbourFlagsAsm.hpp" + +#include "OpenSHC/Globals/DAT_LandscapeState.hpp" +#include "OpenSHC/Globals/DAT_PathFindingState.hpp" +#include "OpenSHC/Globals/DAT_TerrainDefinedData.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_BORDER; + using OpenSHC::Map::LogicHelpers::L_BORDER_EDGE; + using OpenSHC::Map::LogicHelpers::L_BUILDING; + using OpenSHC::Map::LogicHelpers::L_KEEP_NON_MANOR_HOUSE; + using OpenSHC::Map::LogicHelpers::L_MARSH; + using OpenSHC::Map::LogicHelpers::L_MOAT; + using OpenSHC::Map::LogicHelpers::L_RIVER; + using OpenSHC::Map::LogicHelpers::L_ROCKY; + using OpenSHC::Map::LogicHelpers::L_SEA; + using OpenSHC::Map::LogicHelpers::L_WALL_OR_GATEHOUSE; + + // FUNCTION: STRONGHOLDCRUSADER 0x00502680 + void TileMapState::useTerrainHeightBrush(int tile, uint y, uint brush, undefined4 mapper) + { + int baseTile = tile; + uint baseY = y; + int brushSize = DAT_TerrainDefinedData::instance.BrushSizeArray[brush]; + + int highest = 0; + /* the original reuses the brush parameter to hold the lowest height seen */ + brush = 200; + if (brushSize > 0) { + int index = 0; + do { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getTileForBrush, this)( + 1, index, &tile, (int*)&y, baseTile, baseY); + if ((this->LogicLayer[tile] & (L_BORDER | L_BORDER_EDGE)) == 0) { + if ((int)(uint)this->HeightLayer[tile] > highest) { + highest = this->HeightLayer[tile]; + } + if ((int)(uint)this->HeightLayer[tile] < (int)brush) { + brush = this->HeightLayer[tile]; + } + } + index++; + } while (index < brushSize); + } + + int average = (int)(brush + highest) / 2; + tile = baseTile; + y = baseY; + for (int index = 0; index < brushSize; index++) { + MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getTileForBrush, this)( + 1, index, &tile, (int*)&y, baseTile, baseY); + int brushTile = tile; + if ((this->LogicLayer[brushTile] & (L_BORDER | L_BORDER_EDGE)) != 0) { + continue; + } + if ((this->LogicLayer[brushTile] + & (L_SEA | L_WALL_OR_GATEHOUSE | L_BUILDING | L_KEEP_NON_MANOR_HOUSE | L_MARSH | L_MOAT)) + != 0) { + continue; + } + if (this->BuildingLayer[brushTile] != 0) { + continue; + } + + this->HeightLayer[brushTile] = this->HeightLayer[brushTile] + 1; + if ((short)mapper == 0) { + /* mapper min */ + this->HeightLayer[brushTile] = 8; + this->Logic2Layer[brushTile] = this->Logic2Layer[brushTile] & 0xf3; + } else if ((short)mapper == 1) { + /* mapper max, bug:fixme: is 156 really the maximum height? */ + this->HeightLayer[brushTile] = 156; + this->LogicLayer[brushTile] = this->LogicLayer[brushTile] | 0x8000; + } else if ((short)mapper == 5) { + this->HeightLayer[brushTile] = 100; + } else if ((short)mapper == 2) { + /* scale towards the brush average, in eighths of the ratio to it */ + int ratio; + if (average != 0) { + ratio = this->HeightLayer[brushTile] * 100 / average; + } else { + ratio = 100; + } + ratio = ratio / 8 + 100; + ratio = ratio * this->HeightLayer[brushTile] / 100; + if (ratio > 0x9c) { + ratio = 0x9c; + } + this->HeightLayer[brushTile] = (byte)ratio; + } + + if ((this->LogicLayer[brushTile] & L_ROCKY) != 0) { + int organism = this->OrganismLayer[brushTile]; + if (organism >= 2000) { + MACRO_CALL_MEMBER(OpenSHC::Map::LandscapeState_Func::removeRock, DAT_LandscapeState::ptr)( + organism - 2000); + } + } + this->LogicLayer[brushTile] = this->LogicLayer[brushTile] & ~L_ROCKY; + if (this->HeightLayer[brushTile] < 8) { + this->HeightLayer[brushTile] = 8; + } + if (this->HeightLayer[brushTile] > 0x9c) { + this->HeightLayer[brushTile] = 0x9c; + } + this->DefaultHeightLayer[brushTile] = this->HeightLayer[brushTile]; + if ((this->LogicLayer[brushTile] & L_RIVER) != 0) { + this->HeightLayer[brushTile] = this->HeightLayer[brushTile] - 8; + } + uint brushY = y; + this->DAT_SomeTile = brushTile; + this->DAT_SomeY = brushY; + + /* handwritten assembly in the original: mark this tile and its eight neighbours changed */ + MACRO_MARK_CHANGED_NEIGHBOURS() + MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::updatePathLinkagesInAllEightDirections, + DAT_PathFindingState::ptr)(brushY, brushTile); + } + this->forceUpdateLogicalAndMiscDisplayLayers = 1; + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/validateBuildingPlacementAtTile.cpp b/src/OpenSHC/Map/TileMapState/validateBuildingPlacementAtTile.cpp new file mode 100644 index 0000000000..de01bd319c --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/validateBuildingPlacementAtTile.cpp @@ -0,0 +1,63 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Map/Buildings/BuildingType.hpp" +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +#include "OpenSHC/Globals/DAT_BuildingsState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_BUILDING; + using OpenSHC::Map::LogicHelpers::L_KEEP_NON_MANOR_HOUSE; + using OpenSHC::Map::LogicHelpers::L_WALL_OR_GATEHOUSE; + + using OpenSHC::Map::Buildings::BuildingType; + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x004F9DF0 + void TileMapState::validateBuildingPlacementAtTile(int playerID, int x, int y) + { + this->buildingPlacementFail = FALSE; + int tile = DAT_ViewportRenderState::instance.translationMatrix[y].addXgetTile + x; + int buildingID = this->BuildingLayer[tile]; + if (buildingID < 1 || (DAT_BuildingsState::instance.buildings[buildingID].owner != playerID && playerID != 0)) { + this->buildingPlacementFail = TRUE; + } + if ((this->LogicLayer[tile] & L_WALL_OR_GATEHOUSE) != 0 && this->BuildingLayer[tile] == 0) { + if ((this->WallOwnerLayer[tile] & 7) + 1 != playerID) { + return; + } + this->buildingPlacementFail = FALSE; + } + if ((this->LogicLayer[tile] & (L_BUILDING | L_KEEP_NON_MANOR_HOUSE)) == 0 + && DAT_BuildingsState::instance.buildings[buildingID].buildingType + != OpenSHC::Map::Buildings::BT_GATEHOUSELARGE + && DAT_BuildingsState::instance.buildings[buildingID].buildingType + != OpenSHC::Map::Buildings::BT_GATEHOUSESMALL + && DAT_BuildingsState::instance.buildings[buildingID].buildingType != OpenSHC::Map::Buildings::BT_WOODGATE1 + && DAT_BuildingsState::instance.buildings[buildingID].buildingType != OpenSHC::Map::Buildings::BT_WOODGATE2 + && DAT_BuildingsState::instance.buildings[buildingID].buildingType != OpenSHC::Map::Buildings::BT_KEEPDOOR + && DAT_BuildingsState::instance.buildings[buildingID].buildingType != OpenSHC::Map::Buildings::BT_DRAWBRIDGE + && DAT_BuildingsState::instance.buildings[buildingID].buildingType != OpenSHC::Map::Buildings::BT_CAMPGROUND + && DAT_BuildingsState::instance.buildings[buildingID].buildingType + != OpenSHC::Map::Buildings::BT_PARADEGROUND + && DAT_BuildingsState::instance.buildings[buildingID].buildingType + != OpenSHC::Map::Buildings::BT_PARADEGROUND2 + && DAT_BuildingsState::instance.buildings[buildingID].buildingType + != OpenSHC::Map::Buildings::BT_PARADEGROUND3 + && DAT_BuildingsState::instance.buildings[buildingID].buildingType + != OpenSHC::Map::Buildings::BT_PARADEGROUND4 + && DAT_BuildingsState::instance.buildings[buildingID].buildingType + != OpenSHC::Map::Buildings::BT_PARADEGROUND5 + && DAT_BuildingsState::instance.buildings[buildingID].buildingType != OpenSHC::Map::Buildings::BT_CAMPFIRE + && DAT_BuildingsState::instance.buildings[buildingID].buildingType + != OpenSHC::Map::Buildings::BT_KILLINGPIT) { + this->buildingPlacementFail = TRUE; + } + this->cursorTargetID = buildingID; + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/validateWallBuildPath.cpp b/src/OpenSHC/Map/TileMapState/validateWallBuildPath.cpp new file mode 100644 index 0000000000..0b8ff95e23 --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/validateWallBuildPath.cpp @@ -0,0 +1,273 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" +#include "OpenSHC/Game/GameMode.hpp" +#include "OpenSHC/Game/GameMode2.hpp" +#include "OpenSHC/Map/Buildings/BuildingFailReasonEnum.hpp" +#include "OpenSHC/Map/Units/UnitType.hpp" +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +#include "OpenSHC/Globals/DAT_GameCore.hpp" +#include "OpenSHC/Globals/DAT_GameState.hpp" +#include "OpenSHC/Globals/DAT_GameSynchronyState.hpp" +#include "OpenSHC/Globals/DAT_LandscapeState.hpp" +#include "OpenSHC/Globals/DAT_PathFindingState.hpp" +#include "OpenSHC/Globals/DAT_UnitsState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_BORDER; + using OpenSHC::Map::LogicHelpers::L_BUILDING; + using OpenSHC::Map::LogicHelpers::L_FORD; + using OpenSHC::Map::LogicHelpers::L_KEEP_NON_MANOR_HOUSE; + using OpenSHC::Map::LogicHelpers::L_MARSH; + using OpenSHC::Map::LogicHelpers::L_MOAT; + using OpenSHC::Map::LogicHelpers::L_PLAIN1_AND_FARM; + using OpenSHC::Map::LogicHelpers::L_RIVER; + using OpenSHC::Map::LogicHelpers::L_SEA; + using OpenSHC::Map::LogicHelpers::L_TREE; + using OpenSHC::Map::LogicHelpers::L_TREE_VARIATION; + using OpenSHC::Map::LogicHelpers::L_WALL_OR_GATEHOUSE; + + using OpenSHC::Game::GameMode; + using OpenSHC::Game::GameMode2; + using OpenSHC::Map::Buildings::BuildingFailReasonEnum; + using OpenSHC::Map::Units::UnitType; + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x005029D0 + void TileMapState::validateWallBuildPath(int playerID, uint x1, uint y1, uint x2, uint y2, undefined4 command) + { + int budget = 0; + int overshoot = 2; + int enemyRange; + int searchRange; + if (DAT_GameSynchronyState::instance.currentGameMode != OpenSHC::Game::GM_SOLITARY) { + enemyRange = 0xf; + searchRange = 7; + } else { + enemyRange = 0x1e; + searchRange = 0x1e; + } + this->buildingPlacementFail = FALSE; + this->illegalBuild = TRUE; + this->field118_0x554920 = 0; + if (x1 > 399 || y1 > 399 || DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[y1 * 400 + x1] == 0) { + this->buildingPlacementFail = TRUE; + return; + } + if (x2 > 399 || y2 > 399 || DAT_ViewportRenderState::instance.DAT_BinaryTileMap400x400[y2 * 400 + x2] == 0) { + this->buildingPlacementFail = TRUE; + return; + } + + int* translation = &DAT_ViewportRenderState::instance.translationMatrix[y1].addXgetTile; + int tile = *translation + x1; + this->DAT_SomeY = y1; + this->DAT_SomeTile = tile; + if ((short)command == 0x1b) { + /* a stair needs an enclosed wall to lean against, and enough height on it */ + if (MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::isTileEnclosedByWallsOrGates, this)(tile, y1) + == FALSE) { + return; + } + this->maxWallHeightInPath + = MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getMaxWallHeightInBrushArea, this)(tile, y1); + if (this->maxWallHeightInPath < 0x11) { + return; + } + budget = this->maxWallHeightInPath; + } else if ((short)command == 0x1a + && MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::isTileEnclosedByWalls, this)(tile, y1) == 0) { + this->buildingPlacementFailReason = (BuildingFailReasonEnum)0x13; + return; + } + + int upY = y1 - y2; + int downY = y2 - y1; + int rightX = x2 - x1; + this->field118_0x554920 = 1; + uint y = y1; + uint x = x1; + int leftX = x1 - x2; + do { + tile = *translation + x; + uint logic = this->LogicLayer[tile]; + if ((logic & (L_PLAIN1_AND_FARM | L_BORDER)) != 0) { + return; + } + if ((logic & (L_SEA | L_BUILDING | L_KEEP_NON_MANOR_HOUSE | L_MARSH | L_MOAT)) != 0) { + return; + } + if (this->BuildingLayer[tile] != 0) { + return; + } + if ((logic & (L_TREE | L_TREE_VARIATION)) != 0 && this->OrganismLayer[tile] != 0 + && this->OrganismLayer[tile] < 2000) { + /* scrub can be built through, a real tree cannot */ + switch (DAT_LandscapeState::instance.trees[this->OrganismLayer[tile]].treeType) { + case (TreeType)5: + case (TreeType)6: + case (TreeType)7: + case (TreeType)8: + case (TreeType)9: + case (TreeType)0xa: + case (TreeType)0xb: + case (TreeType)0xc: + case (TreeType)0xd: + case (TreeType)0xe: + case (TreeType)0x10: + case (TreeType)0x11: + case (TreeType)0x12: + case (TreeType)0x13: + break; + default: + return; + } + } + if ((logic & (L_RIVER | L_FORD)) != 0) { + return; + } + if ((char)logic < 0) { + return; + } + if (this->UnitLayer[tile] != 0 && (logic & L_WALL_OR_GATEHOUSE) == 0 + && DAT_UnitsState::instance.units[(short)this->UnitLayer[tile]].unitType + != OpenSHC::Map::Units::UT_CHICKEN) { + return; + } + if (DAT_GameCore::instance.gameMode_2 != OpenSHC::Game::GM_EDITOR + && DAT_GameCore::instance.gameMode_2 != OpenSHC::Game::GM_SIEGE_THAT + && MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::isEnemyTooCloseUnk, + DAT_PathFindingState::ptr)(playerID, x, y, enemyRange) + != FALSE) { + this->buildingPlacementFailReason = (BuildingFailReasonEnum)0x11; + return; + } + if (DAT_GameSynchronyState::instance.currentGameMode != OpenSHC::Game::GM_SOLITARY) { + if (MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::isOpponentBuildingInRange, + DAT_PathFindingState::ptr)(playerID, x, y, searchRange, -1, -1, -1) + != 0) { + if (this->buildingPlacementFailReason == (BuildingFailReasonEnum)0x12) { + return; + } + this->buildingPlacementFailReason = (BuildingFailReasonEnum)0x13; + return; + } + if (DAT_GameSynchronyState::instance.currentGameMode != OpenSHC::Game::GM_SOLITARY) { + int buildRange + = MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::getCastleBuildRangeForMapSize, this)(); + if (MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::isTileInRangeOfKeepRange, + DAT_PathFindingState::ptr)(playerID, x, y, buildRange) + != 0) { + if (this->buildingPlacementFailReason == (BuildingFailReasonEnum)0x12) { + return; + } + this->buildingPlacementFailReason = (BuildingFailReasonEnum)0x13; + return; + } + } + } + if (DAT_GameCore::instance.gameMode_2 == OpenSHC::Game::GM_EDITOR + && MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::isOpponentBuildingInRange, + DAT_PathFindingState::ptr)(playerID, x, y, 7, -1, -1, -1) + != 0) { + this->buildingPlacementFailReason = (BuildingFailReasonEnum)0x11; + return; + } + if (MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::findSomeSuitableLocationUnk, + DAT_PathFindingState::ptr)(playerID, x, y, 2) + != 0) { + this->buildingPlacementFailReason = (BuildingFailReasonEnum)0x11; + return; + } + if (MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::isSignPostWithinDistance, + DAT_PathFindingState::ptr)(x, y, DAT_GameState::instance.mapAndTime.unk_signpostDistance + 5) + != FALSE) { + this->buildingPlacementFailReason = (BuildingFailReasonEnum)0x15; + return; + } + if ((short)command == 0x1a) { + if (MACRO_CALL_MEMBER(OpenSHC::Map::TileMapState_Func::isTileEnclosedByWalls, this)(tile, y) == 0) { + this->buildingPlacementFailReason = (BuildingFailReasonEnum)0x13; + return; + } + } else if ((short)command == 0x1b + && (budget < 0x11 || (this->LogicLayer[tile] & L_WALL_OR_GATEHOUSE) != 0)) { + break; + } + + int stepX = leftX; + if ((int)x < (int)x2) { + stepX = rightX; + } + int stepY = upY; + if ((int)y < (int)y2) { + stepY = downY; + } + if ((short)command == 0x1b) { + if (stepY < stepX) { + if ((int)x < (int)x2) { + leftX = leftX + 1; + x = x + 1; + rightX = rightX - 1; + } else { + leftX = leftX - 1; + x = x - 1; + rightX = rightX + 1; + } + } else if (stepY > 0) { + if ((int)y < (int)y2) { + translation = translation + 3; + upY = upY + 1; + y = y + 1; + downY = downY - 1; + } else { + translation = translation - 3; + upY = upY - 1; + y = y - 1; + downY = downY + 1; + } + } else { + overshoot = overshoot - 1; + } + } else { + if (stepX != 0) { + if ((int)x < (int)x2) { + leftX = leftX + 1; + x = x + 1; + rightX = rightX - 1; + } else { + leftX = leftX - 1; + x = x - 1; + rightX = rightX + 1; + } + } + if (stepY != 0) { + if ((int)y < (int)y2) { + translation = translation + 3; + upY = upY + 1; + y = y + 1; + downY = downY - 1; + } else { + translation = translation - 3; + upY = upY - 1; + y = y - 1; + downY = downY + 1; + } + } + if (x == x2 && y == y2) { + overshoot = overshoot - 1; + } + } + if (budget > 0x10) { + budget = budget - 0x10; + } + } while (x != x2 || y != y2 || overshoot != 0); + this->illegalBuild = FALSE; + } + +} +} diff --git a/src/OpenSHC/Map/TileMapState/validateWallPlacementAtTile.cpp b/src/OpenSHC/Map/TileMapState/validateWallPlacementAtTile.cpp new file mode 100644 index 0000000000..8c4837c46e --- /dev/null +++ b/src/OpenSHC/Map/TileMapState/validateWallPlacementAtTile.cpp @@ -0,0 +1,69 @@ +#include "../TileMapState.func.hpp" + +#include "OpenSHC/Map/Navigation/PathFindingState.func.hpp" +#include "OpenSHC/Map/Units/UnitLogicState.hpp" +#include "OpenSHC/WindowsHelper/Enums/BOOLEnum.hpp" + +#include "OpenSHC/Globals/DAT_PathFindingState.hpp" +#include "OpenSHC/Globals/DAT_UnitsState.hpp" +#include "OpenSHC/Globals/DAT_ViewportRenderState.hpp" + +namespace OpenSHC { +namespace Map { + + using OpenSHC::Map::LogicHelpers::L_BORDER; + using OpenSHC::Map::LogicHelpers::L_BUILDING; + using OpenSHC::Map::LogicHelpers::L_FORD; + using OpenSHC::Map::LogicHelpers::L_MARSH; + using OpenSHC::Map::LogicHelpers::L_MOAT; + using OpenSHC::Map::LogicHelpers::L_PLAIN1_AND_FARM; + using OpenSHC::Map::LogicHelpers::L_RIVER; + using OpenSHC::Map::LogicHelpers::L_ROCKY; + using OpenSHC::Map::LogicHelpers::L_SEA; + using OpenSHC::Map::LogicHelpers::L_WALL_OR_GATEHOUSE; + + using OpenSHC::Map::Units::UnitLogicState; + using OpenSHC::WindowsHelper::Enums::BOOLEnum; + + // FUNCTION: STRONGHOLDCRUSADER 0x004F94A0 + void TileMapState::validateWallPlacementAtTile(int playerID, uint x, uint y, MappersEnum param_4) + { + this->illegalBuild = TRUE; + int tile = DAT_ViewportRenderState::instance.translationMatrix[y].addXgetTile + x; + uint logic = this->LogicLayer[tile]; + if ((logic & L_WALL_OR_GATEHOUSE) != 0 && (char)this->DamageLayer[tile] <= 11) { + return; + } + if ((logic & L_BUILDING) != 0) { + return; + } + if (this->BuildingLayer[tile] != 0) { + return; + } + if ((logic & (L_PLAIN1_AND_FARM | L_BORDER)) != 0) { + return; + } + if ((logic & (L_SEA | L_ROCKY | L_RIVER | L_FORD | L_MARSH | L_MOAT)) != 0) { + return; + } + if (MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::isEnemyTooCloseUnk, + DAT_PathFindingState::ptr)(playerID, x, y, 5) + != FALSE) { + return; + } + if (MACRO_CALL_MEMBER(OpenSHC::Map::Navigation::PathFindingState_Func::findSomeSuitableLocationUnk, + DAT_PathFindingState::ptr)(playerID, x, y, 2) + != 0) { + return; + } + + if (this->UnitLayer[tile] != 0 && (this->LogicLayer[tile] & L_WALL_OR_GATEHOUSE) == 0 + && ((undefined2)param_4 == OpenSHC::Commands::M_MAPPER_CRENAL + || (undefined2)param_4 == OpenSHC::Commands::M_MAPPER_CRENAL2)) { + DAT_UnitsState::instance.units[(short)this->UnitLayer[tile]].logicalState = OpenSHC::Map::Units::ULS_REMOVE; + } + this->illegalBuild = FALSE; + } + +} +} diff --git a/src/OpenSHC/Map/Units/Unit.hpp b/src/OpenSHC/Map/Units/Unit.hpp index f2c5a11bc2..ba7948e29c 100644 --- a/src/OpenSHC/Map/Units/Unit.hpp +++ b/src/OpenSHC/Map/Units/Unit.hpp @@ -81,7 +81,7 @@ namespace Map { short gmIDUnk; // 0x0000007E length: 2 short displayColorPlayerID; // 0x00000080 length: 2 undefined1 heightDiv10; // 0x00000082 length: 1 - undefined1 padding_0x83[1]; // 0x00000083 length: 1 + undefined1 field_0x83; // 0x00000083 length: 1 short field58_0x84; // 0x00000084 length: 2 short field59_0x86; // 0x00000086 length: 2 short field60_0x88; // 0x00000088 length: 2 diff --git a/status/addresses-SHC-3BB0A8C1.txt b/status/addresses-SHC-3BB0A8C1.txt index dcc0e5208a..91892871c5 100644 --- a/status/addresses-SHC-3BB0A8C1.txt +++ b/status/addresses-SHC-3BB0A8C1.txt @@ -38739,37 +38739,37 @@ SHC_3BB0A8C1_0x004F6A70 | 100.0% | Reimplemented SHC_3BB0A8C1_0x004F6A80 | 0.0% | Pending -SHC_3BB0A8C1_0x004F6AE0 | 0.0% | Pending +SHC_3BB0A8C1_0x004F6AE0 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x004F6B20 | 0.0% | Pending +SHC_3BB0A8C1_0x004F6B20 | 30.1% | row counter costs a spill SHC_3BB0A8C1_0x004F6C20 | 0.0% | Pending -SHC_3BB0A8C1_0x004F6C60 | 0.0% | Pending +SHC_3BB0A8C1_0x004F6C60 | 92.3% | border index regalloc -SHC_3BB0A8C1_0x004F6CF0 | 0.0% | Pending +SHC_3BB0A8C1_0x004F6CF0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x004F6DC0 | 0.0% | Pending -SHC_3BB0A8C1_0x004F6F90 | 0.0% | Pending +SHC_3BB0A8C1_0x004F6F90 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x004F6FD0 | 0.0% | Pending +SHC_3BB0A8C1_0x004F6FD0 | 98.3% | unit loop regalloc SHC_3BB0A8C1_0x004F70B0 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x004F70D0 | 0.0% | Pending +SHC_3BB0A8C1_0x004F70D0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x004F70E0 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x004F70F0 | 0.0% | Pending +SHC_3BB0A8C1_0x004F70F0 | 48.0% | signed height compare SHC_3BB0A8C1_0x004F7140 | 0.0% | Pending SHC_3BB0A8C1_0x004F7170 | 0.0% | Pending -SHC_3BB0A8C1_0x004F79D0 | 0.0% | Pending +SHC_3BB0A8C1_0x004F79D0 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x004F7A80 | 0.0% | Pending +SHC_3BB0A8C1_0x004F7A80 | 21.9% | 20.69% regalloc, frame size SHC_3BB0A8C1_0x004F7E50 | 0.0% | Pending @@ -38787,13 +38787,13 @@ SHC_3BB0A8C1_0x004F80D4 | 0.0% | Pending SHC_3BB0A8C1_0x004F80D8 | 0.0% | Pending -SHC_3BB0A8C1_0x004F80E0 | 0.0% | Pending +SHC_3BB0A8C1_0x004F80E0 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x004F8160 | 0.0% | Pending +SHC_3BB0A8C1_0x004F8160 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x004F81D0 | 0.0% | Pending +SHC_3BB0A8C1_0x004F81D0 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x004F8210 | 0.0% | Pending +SHC_3BB0A8C1_0x004F8210 | 94.7% | switch table vs compare chain SHC_3BB0A8C1_0x004F8288 | 0.0% | Pending @@ -38995,7 +38995,7 @@ SHC_3BB0A8C1_0x004F82F0 | 0.0% | Pending SHC_3BB0A8C1_0x004F82F1 | 0.0% | Pending -SHC_3BB0A8C1_0x004F8300 | 0.0% | Pending +SHC_3BB0A8C1_0x004F8300 | 99.3% | global instance access SHC_3BB0A8C1_0x004F8454 | 0.0% | Pending @@ -39355,43 +39355,43 @@ SHC_3BB0A8C1_0x004F8523 | 0.0% | Pending SHC_3BB0A8C1_0x004F8524 | 0.0% | Pending -SHC_3BB0A8C1_0x004F8530 | 0.0% | Pending +SHC_3BB0A8C1_0x004F8530 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x004F85B0 | 0.0% | Pending +SHC_3BB0A8C1_0x004F85B0 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x004F8640 | 0.0% | Pending +SHC_3BB0A8C1_0x004F8640 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x004F86D0 | 0.0% | Pending +SHC_3BB0A8C1_0x004F86D0 | 98.4% | direction chain regalloc -SHC_3BB0A8C1_0x004F8780 | 0.0% | Pending +SHC_3BB0A8C1_0x004F8780 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x004F8840 | 0.0% | Pending +SHC_3BB0A8C1_0x004F8840 | 93.7% | direction chain order -SHC_3BB0A8C1_0x004F8900 | 0.0% | Pending +SHC_3BB0A8C1_0x004F8900 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x004F89C0 | 0.0% | Pending +SHC_3BB0A8C1_0x004F89C0 | 59.1% | orientation blocks not shared -SHC_3BB0A8C1_0x004F8A40 | 0.0% | Pending +SHC_3BB0A8C1_0x004F8A40 | 87.2% | shr vs sar on logic bit -SHC_3BB0A8C1_0x004F8AC0 | 0.0% | Pending +SHC_3BB0A8C1_0x004F8AC0 | 90.7% | shr vs sar on logic bit -SHC_3BB0A8C1_0x004F8B50 | 0.0% | Pending +SHC_3BB0A8C1_0x004F8B50 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x004F8BD0 | 0.0% | Pending +SHC_3BB0A8C1_0x004F8BD0 | 44.2% | 44.57% regalloc -SHC_3BB0A8C1_0x004F9000 | 0.0% | Pending +SHC_3BB0A8C1_0x004F9000 | 59.5% | owner store tail-merge -SHC_3BB0A8C1_0x004F9220 | 0.0% | Pending +SHC_3BB0A8C1_0x004F9220 | 88.1% | owner store tail-merge -SHC_3BB0A8C1_0x004F93E0 | 0.0% | Pending +SHC_3BB0A8C1_0x004F93E0 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x004F94A0 | 0.0% | Pending +SHC_3BB0A8C1_0x004F94A0 | 67.2% | logic masks merged by cl -SHC_3BB0A8C1_0x004F9590 | 0.0% | Pending +SHC_3BB0A8C1_0x004F9590 | 62.5% | natural x/y, regalloc differs SHC_3BB0A8C1_0x004F9630 | 0.0% | Pending -SHC_3BB0A8C1_0x004F9880 | 0.0% | Pending +SHC_3BB0A8C1_0x004F9880 | 100.0% | Reimplemented SHC_3BB0A8C1_0x004F990C | 0.0% | Pending @@ -39407,13 +39407,13 @@ SHC_3BB0A8C1_0x004F9920 | 0.0% | Pending SHC_3BB0A8C1_0x004F9924 | 0.0% | Pending -SHC_3BB0A8C1_0x004F9930 | 0.0% | Pending +SHC_3BB0A8C1_0x004F9930 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x004F9980 | 0.0% | Pending +SHC_3BB0A8C1_0x004F9980 | 100.0% | Reimplemented SHC_3BB0A8C1_0x004F99D0 | 0.0% | Pending -SHC_3BB0A8C1_0x004F9A60 | 0.0% | Pending +SHC_3BB0A8C1_0x004F9A60 | 49.7% | 49.70% global instance base SHC_3BB0A8C1_0x004F9D64 | 0.0% | Pending @@ -39649,17 +39649,17 @@ SHC_3BB0A8C1_0x004F9DE9 | 0.0% | Pending SHC_3BB0A8C1_0x004F9DEA | 0.0% | Pending -SHC_3BB0A8C1_0x004F9DF0 | 0.0% | Pending +SHC_3BB0A8C1_0x004F9DF0 | 97.1% | buildingType chain regalloc -SHC_3BB0A8C1_0x004F9F00 | 0.0% | Pending +SHC_3BB0A8C1_0x004F9F00 | 82.3% | global instance access -SHC_3BB0A8C1_0x004FA000 | 0.0% | Pending +SHC_3BB0A8C1_0x004FA000 | 33.9% | 33.90% pointer local frame -SHC_3BB0A8C1_0x004FA2D0 | 0.0% | Pending +SHC_3BB0A8C1_0x004FA2D0 | 47.4% | 47.37% cold block layout regal -SHC_3BB0A8C1_0x004FA460 | 0.0% | Pending +SHC_3BB0A8C1_0x004FA460 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x004FA550 | 0.0% | Pending +SHC_3BB0A8C1_0x004FA550 | 100.0% | Reimplemented SHC_3BB0A8C1_0x004FA5DC | 0.0% | Pending @@ -40343,33 +40343,33 @@ SHC_3BB0A8C1_0x004FA759 | 0.0% | Pending SHC_3BB0A8C1_0x004FA75A | 0.0% | Pending -SHC_3BB0A8C1_0x004FA760 | 0.0% | Pending +SHC_3BB0A8C1_0x004FA760 | 56.3% | 61.02% offset array partition SHC_3BB0A8C1_0x004FA8D0 | 0.0% | Pending -SHC_3BB0A8C1_0x004FA9D0 | 0.0% | Pending +SHC_3BB0A8C1_0x004FA9D0 | 96.3% | LTCG, loop alignment -SHC_3BB0A8C1_0x004FAA30 | 0.0% | Pending +SHC_3BB0A8C1_0x004FAA30 | 91.9% | Style pass, asm differs -SHC_3BB0A8C1_0x004FAAB0 | 0.0% | Pending +SHC_3BB0A8C1_0x004FAAB0 | 59.3% | Style pass, asm differs SHC_3BB0A8C1_0x004FAAE0 | 0.0% | Pending -SHC_3BB0A8C1_0x004FAB70 | 0.0% | Pending +SHC_3BB0A8C1_0x004FAB70 | 81.0% | int local for short field read -SHC_3BB0A8C1_0x004FAC70 | 0.0% | Pending +SHC_3BB0A8C1_0x004FAC70 | 84.7% | ecx not kept across callee -SHC_3BB0A8C1_0x004FAD20 | 0.0% | Pending +SHC_3BB0A8C1_0x004FAD20 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x004FAD70 | 0.0% | Pending +SHC_3BB0A8C1_0x004FAD70 | 77.7% | ecx not kept across callee -SHC_3BB0A8C1_0x004FAE50 | 0.0% | Pending +SHC_3BB0A8C1_0x004FAE50 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x004FAEE0 | 0.0% | Pending +SHC_3BB0A8C1_0x004FAEE0 | 74.2% | LTCG, regalloc differs -SHC_3BB0A8C1_0x004FAF70 | 0.0% | Pending +SHC_3BB0A8C1_0x004FAF70 | 98.5% | offset walk regalloc -SHC_3BB0A8C1_0x004FB0C0 | 0.0% | Pending +SHC_3BB0A8C1_0x004FB0C0 | 62.4% | LTCG, rotation hoisted SHC_3BB0A8C1_0x004FB2E0 | 0.0% | Pending @@ -40565,25 +40565,25 @@ SHC_3BB0A8C1_0x004FB354 | 0.0% | Pending SHC_3BB0A8C1_0x004FB358 | 0.0% | Pending -SHC_3BB0A8C1_0x004FB360 | 0.0% | Pending +SHC_3BB0A8C1_0x004FB360 | 79.0% | ecx not kept across callee -SHC_3BB0A8C1_0x004FB3F0 | 0.0% | Pending +SHC_3BB0A8C1_0x004FB3F0 | 34.3% | XYPair stride regalloc -SHC_3BB0A8C1_0x004FB4D0 | 0.0% | Pending +SHC_3BB0A8C1_0x004FB4D0 | 43.4% | signed height compares, was 42 -SHC_3BB0A8C1_0x004FB770 | 0.0% | Pending +SHC_3BB0A8C1_0x004FB770 | 85.5% | int locals for short field rea SHC_3BB0A8C1_0x004FB7D0 | 0.0% | Pending -SHC_3BB0A8C1_0x004FB8E0 | 0.0% | Pending +SHC_3BB0A8C1_0x004FB8E0 | 97.0% | LTCG, add operand order -SHC_3BB0A8C1_0x004FB970 | 0.0% | Pending +SHC_3BB0A8C1_0x004FB970 | 96.8% | LTCG, add operand order SHC_3BB0A8C1_0x004FB990 | 0.0% | Pending -SHC_3BB0A8C1_0x004FB9E0 | 0.0% | Pending +SHC_3BB0A8C1_0x004FB9E0 | 77.8% | LTCG, regalloc differs -SHC_3BB0A8C1_0x004FBC30 | 0.0% | Pending +SHC_3BB0A8C1_0x004FBC30 | 100.0% | Reimplemented SHC_3BB0A8C1_0x004FBC6C | 0.0% | Pending @@ -41077,35 +41077,35 @@ SHC_3BB0A8C1_0x004FBD6F | 0.0% | Pending SHC_3BB0A8C1_0x004FBD70 | 0.0% | Pending -SHC_3BB0A8C1_0x004FBD80 | 0.0% | Pending +SHC_3BB0A8C1_0x004FBD80 | 74.1% | step logic fixed, regalloc -SHC_3BB0A8C1_0x004FBE70 | 0.0% | Pending +SHC_3BB0A8C1_0x004FBE70 | 87.2% | 85.48% regalloc -SHC_3BB0A8C1_0x004FC0B0 | 0.0% | Pending +SHC_3BB0A8C1_0x004FC0B0 | 36.4% | 36.36% regalloc -SHC_3BB0A8C1_0x004FC280 | 0.0% | Pending +SHC_3BB0A8C1_0x004FC280 | 85.2% | XYPair base regalloc -SHC_3BB0A8C1_0x004FC340 | 0.0% | Pending +SHC_3BB0A8C1_0x004FC340 | 62.4% | LogicLayer walk regalloc -SHC_3BB0A8C1_0x004FC490 | 0.0% | Pending +SHC_3BB0A8C1_0x004FC490 | 54.1% | 56.42% array base regalloc -SHC_3BB0A8C1_0x004FC650 | 0.0% | Pending +SHC_3BB0A8C1_0x004FC650 | 45.5% | orientation chain regalloc -SHC_3BB0A8C1_0x004FC7C0 | 0.0% | Pending +SHC_3BB0A8C1_0x004FC7C0 | 79.0% | setg vs sbb/neg -SHC_3BB0A8C1_0x004FC810 | 0.0% | Pending +SHC_3BB0A8C1_0x004FC810 | 81.8% | signed height compares, was 67 -SHC_3BB0A8C1_0x004FC9E0 | 0.0% | Pending +SHC_3BB0A8C1_0x004FC9E0 | 66.7% | signed layer reads -SHC_3BB0A8C1_0x004FDB00 | 0.0% | Pending +SHC_3BB0A8C1_0x004FDB00 | 63.1% | signed layer reads -SHC_3BB0A8C1_0x004FF080 | 0.0% | Pending +SHC_3BB0A8C1_0x004FF080 | 27.3% | 27.06% regalloc SHC_3BB0A8C1_0x004FF420 | 0.0% | Pending -SHC_3BB0A8C1_0x004FF870 | 0.0% | Pending +SHC_3BB0A8C1_0x004FF870 | 74.7% | __asm macro; global not nameable -SHC_3BB0A8C1_0x004FF990 | 0.0% | Pending +SHC_3BB0A8C1_0x004FF990 | 74.5% | switch arm regalloc SHC_3BB0A8C1_0x004FFAAC | 0.0% | Pending @@ -41259,9 +41259,9 @@ SHC_3BB0A8C1_0x004FFB02 | 0.0% | Pending SHC_3BB0A8C1_0x004FFB03 | 0.0% | Pending -SHC_3BB0A8C1_0x004FFB10 | 0.0% | Pending +SHC_3BB0A8C1_0x004FFB10 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x004FFBA0 | 0.0% | Pending +SHC_3BB0A8C1_0x004FFBA0 | 41.0% | single exit, owner test merge SHC_3BB0A8C1_0x004FFECC | 0.0% | Pending @@ -41349,7 +41349,7 @@ SHC_3BB0A8C1_0x004FFF01 | 0.0% | Pending SHC_3BB0A8C1_0x004FFF02 | 0.0% | Pending -SHC_3BB0A8C1_0x004FFF10 | 0.0% | Pending +SHC_3BB0A8C1_0x004FFF10 | 44.0% | switch arm regalloc SHC_3BB0A8C1_0x00500060 | 0.0% | Pending @@ -41421,55 +41421,55 @@ SHC_3BB0A8C1_0x00500091 | 0.0% | Pending SHC_3BB0A8C1_0x005000A0 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x005000E0 | 0.0% | Pending +SHC_3BB0A8C1_0x005000E0 | 48.7% | owner reload per unrolled step -SHC_3BB0A8C1_0x00500180 | 0.0% | Pending +SHC_3BB0A8C1_0x00500180 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00500210 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x00500250 | 0.0% | Pending +SHC_3BB0A8C1_0x00500250 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x00500290 | 0.0% | Pending +SHC_3BB0A8C1_0x00500290 | 100.0% | Reimplemented SHC_3BB0A8C1_0x005002D0 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x00500310 | 0.0% | Pending +SHC_3BB0A8C1_0x00500310 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x00500370 | 0.0% | Pending +SHC_3BB0A8C1_0x00500370 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x005003D0 | 0.0% | Pending +SHC_3BB0A8C1_0x005003D0 | 54.3% | moat row walk regalloc -SHC_3BB0A8C1_0x00500500 | 0.0% | Pending +SHC_3BB0A8C1_0x00500500 | 86.5% | moat field reload/regalloc -SHC_3BB0A8C1_0x005005F0 | 0.0% | Pending +SHC_3BB0A8C1_0x005005F0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00500640 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00500680 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x005006C0 | 0.0% | Pending +SHC_3BB0A8C1_0x005006C0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00500720 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00500750 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x00500790 | 0.0% | Pending +SHC_3BB0A8C1_0x00500790 | 100.0% | Reimplemented SHC_3BB0A8C1_0x005007D0 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x00500800 | 0.0% | Pending +SHC_3BB0A8C1_0x00500800 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x00500850 | 0.0% | Pending +SHC_3BB0A8C1_0x00500850 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x00500890 | 0.0% | Pending +SHC_3BB0A8C1_0x00500890 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x00500940 | 0.0% | Pending +SHC_3BB0A8C1_0x00500940 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x00500980 | 0.0% | Pending +SHC_3BB0A8C1_0x00500980 | 81.8% | signed layer read + int locals -SHC_3BB0A8C1_0x00500B50 | 0.0% | Pending +SHC_3BB0A8C1_0x00500B50 | 68.3% | loop guard/regalloc differs -SHC_3BB0A8C1_0x00500BB0 | 0.0% | Pending +SHC_3BB0A8C1_0x00500BB0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00500C20 | 100.0% | Reimplemented @@ -41541,11 +41541,11 @@ SHC_3BB0A8C1_0x00501760 | 0.0% | Pending SHC_3BB0A8C1_0x005017A0 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x005017C0 | 0.0% | Pending +SHC_3BB0A8C1_0x005017C0 | 49.0% | global instance access -SHC_3BB0A8C1_0x00501A20 | 0.0% | Pending +SHC_3BB0A8C1_0x00501A20 | 91.7% | 84.72% regalloc -SHC_3BB0A8C1_0x00501B90 | 0.0% | Pending +SHC_3BB0A8C1_0x00501B90 | 100.0% | Reimplemented SHC_3BB0A8C1_0x00501CB0 | 0.0% | Pending @@ -41561,25 +41561,25 @@ SHC_3BB0A8C1_0x00501CC4 | 0.0% | Pending SHC_3BB0A8C1_0x00501CC8 | 0.0% | Pending -SHC_3BB0A8C1_0x00501CD0 | 0.0% | Pending +SHC_3BB0A8C1_0x00501CD0 | 82.0% | brush loop regalloc -SHC_3BB0A8C1_0x00501D90 | 0.0% | Pending +SHC_3BB0A8C1_0x00501D90 | 53.1% | const 1 not pooled in ebx -SHC_3BB0A8C1_0x00501F50 | 0.0% | Pending +SHC_3BB0A8C1_0x00501F50 | 35.6% | asm macro, regalloc differs SHC_3BB0A8C1_0x00501FE0 | 0.0% | Pending -SHC_3BB0A8C1_0x00502110 | 0.0% | Pending +SHC_3BB0A8C1_0x00502110 | 43.3% | asm macro, regalloc differs -SHC_3BB0A8C1_0x00502390 | 0.0% | Pending +SHC_3BB0A8C1_0x00502390 | 28.1% | brush loop regalloc -SHC_3BB0A8C1_0x005024F0 | 0.0% | Pending +SHC_3BB0A8C1_0x005024F0 | 51.8% | 47.37% index spill regalloc -SHC_3BB0A8C1_0x00502680 | 0.0% | Pending +SHC_3BB0A8C1_0x00502680 | 50.0% | asm macro, cold arms inline -SHC_3BB0A8C1_0x00502950 | 0.0% | Pending +SHC_3BB0A8C1_0x00502950 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x005029D0 | 0.0% | Pending +SHC_3BB0A8C1_0x005029D0 | 28.5% | 34.09% this spilled vs regallo SHC_3BB0A8C1_0x00502F14 | 0.0% | Pending @@ -41615,7 +41615,7 @@ SHC_3BB0A8C1_0x00502F29 | 0.0% | Pending SHC_3BB0A8C1_0x00502F2A | 0.0% | Pending -SHC_3BB0A8C1_0x00502F30 | 0.0% | Pending +SHC_3BB0A8C1_0x00502F30 | 33.9% | 36.78% shared blocks as flags SHC_3BB0A8C1_0x0050347C | 0.0% | Pending @@ -41651,11 +41651,11 @@ SHC_3BB0A8C1_0x00503491 | 0.0% | Pending SHC_3BB0A8C1_0x00503492 | 0.0% | Pending -SHC_3BB0A8C1_0x005034A0 | 0.0% | Pending +SHC_3BB0A8C1_0x005034A0 | 54.5% | 57.24% regalloc -SHC_3BB0A8C1_0x00503720 | 0.0% | Pending +SHC_3BB0A8C1_0x00503720 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x005037B0 | 0.0% | Pending +SHC_3BB0A8C1_0x005037B0 | 43.3% | Style pass, asm differs SHC_3BB0A8C1_0x005046A0 | 0.0% | Pending @@ -41959,7 +41959,7 @@ SHC_3BB0A8C1_0x00504A26 | 0.0% | Pending SHC_3BB0A8C1_0x00504A27 | 0.0% | Pending -SHC_3BB0A8C1_0x00504A30 | 0.0% | Pending +SHC_3BB0A8C1_0x00504A30 | 49.5% | global instance access SHC_3BB0A8C1_0x00504E88 | 0.0% | Pending @@ -42069,7 +42069,7 @@ SHC_3BB0A8C1_0x00504ED1 | 0.0% | Pending SHC_3BB0A8C1_0x00504EE0 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x00504F10 | 0.0% | Pending +SHC_3BB0A8C1_0x00504F10 | 30.2% | Style pass, asm differs SHC_3BB0A8C1_0x005050F0 | 0.0% | Pending @@ -42081,25 +42081,25 @@ SHC_3BB0A8C1_0x00505A10 | 0.0% | Pending SHC_3BB0A8C1_0x005060C0 | 0.0% | Pending -SHC_3BB0A8C1_0x00506370 | 0.0% | Pending +SHC_3BB0A8C1_0x00506370 | 53.2% | signed % and / restored -SHC_3BB0A8C1_0x00506AD0 | 0.0% | Pending +SHC_3BB0A8C1_0x00506AD0 | 77.9% | buildingType chain tail-merge -SHC_3BB0A8C1_0x00506BD0 | 0.0% | Pending +SHC_3BB0A8C1_0x00506BD0 | 75.9% | setupBuildingData arg regalloc -SHC_3BB0A8C1_0x00506D40 | 0.0% | Pending +SHC_3BB0A8C1_0x00506D40 | 89.6% | setupBuildingData arg regalloc -SHC_3BB0A8C1_0x00506E10 | 0.0% | Pending +SHC_3BB0A8C1_0x00506E10 | 84.5% | setupBuildingData arg regalloc -SHC_3BB0A8C1_0x00506F40 | 0.0% | Pending +SHC_3BB0A8C1_0x00506F40 | 85.2% | setupBuildingData arg regalloc -SHC_3BB0A8C1_0x00507060 | 0.0% | Pending +SHC_3BB0A8C1_0x00507060 | 90.8% | setupBuildingData arg regalloc -SHC_3BB0A8C1_0x00507130 | 0.0% | Pending +SHC_3BB0A8C1_0x00507130 | 53.1% | setupBuildingData arg regalloc -SHC_3BB0A8C1_0x00507280 | 0.0% | Pending +SHC_3BB0A8C1_0x00507280 | 54.5% | ecx not kept across callee -SHC_3BB0A8C1_0x00507350 | 0.0% | Pending +SHC_3BB0A8C1_0x00507350 | 74.1% | tree switch jump table SHC_3BB0A8C1_0x00507408 | 0.0% | Pending @@ -42135,37 +42135,37 @@ SHC_3BB0A8C1_0x0050741D | 0.0% | Pending SHC_3BB0A8C1_0x0050741E | 0.0% | Pending -SHC_3BB0A8C1_0x00507420 | 0.0% | Pending +SHC_3BB0A8C1_0x00507420 | 44.8% | setupBuildingData arg regalloc -SHC_3BB0A8C1_0x00507560 | 0.0% | Pending +SHC_3BB0A8C1_0x00507560 | 44.8% | setupBuildingData arg regalloc -SHC_3BB0A8C1_0x005076A0 | 0.0% | Pending +SHC_3BB0A8C1_0x005076A0 | 54.7% | was uncompilable; dropped bogu SHC_3BB0A8C1_0x00507830 | 0.0% | Pending -SHC_3BB0A8C1_0x00507BD0 | 0.0% | Pending +SHC_3BB0A8C1_0x00507BD0 | 59.2% | Style pass, asm differs SHC_3BB0A8C1_0x00507D50 | 0.0% | Pending -SHC_3BB0A8C1_0x00507E00 | 0.0% | Pending +SHC_3BB0A8C1_0x00507E00 | 59.2% | Style pass, asm differs SHC_3BB0A8C1_0x00507F80 | 0.0% | Pending -SHC_3BB0A8C1_0x00508030 | 0.0% | Pending +SHC_3BB0A8C1_0x00508030 | 69.3% | LTCG, regalloc differs -SHC_3BB0A8C1_0x00508250 | 0.0% | Pending +SHC_3BB0A8C1_0x00508250 | 40.3% | 39.78% regalloc -SHC_3BB0A8C1_0x00508540 | 0.0% | Pending +SHC_3BB0A8C1_0x00508540 | 52.9% | 55.63% operand order regalloc SHC_3BB0A8C1_0x00508590 | 0.0% | Pending -SHC_3BB0A8C1_0x00508760 | 0.0% | Pending +SHC_3BB0A8C1_0x00508760 | 78.2% | int locals for short field rea -SHC_3BB0A8C1_0x00508870 | 0.0% | Pending +SHC_3BB0A8C1_0x00508870 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x00508910 | 0.0% | Pending +SHC_3BB0A8C1_0x00508910 | 76.9% | LTCG, regalloc differs -SHC_3BB0A8C1_0x00508A00 | 0.0% | Pending +SHC_3BB0A8C1_0x00508A00 | 71.4% | 71.43% jump table, gfx select SHC_3BB0A8C1_0x00508C7C | 0.0% | Pending @@ -42763,11 +42763,11 @@ SHC_3BB0A8C1_0x00508DC2 | 0.0% | Pending SHC_3BB0A8C1_0x00508DC3 | 0.0% | Pending -SHC_3BB0A8C1_0x00508DD0 | 0.0% | Pending +SHC_3BB0A8C1_0x00508DD0 | 43.1% | extra callee-saved reg -SHC_3BB0A8C1_0x00508EC0 | 0.0% | Pending +SHC_3BB0A8C1_0x00508EC0 | 36.6% | int local for short field read -SHC_3BB0A8C1_0x00509180 | 0.0% | Pending +SHC_3BB0A8C1_0x00509180 | 26.3% | Style pass, asm differs SHC_3BB0A8C1_0x0050A74E | 0.0% | Pending @@ -44173,23 +44173,23 @@ SHC_3BB0A8C1_0x00511018 | 0.0% | Pending SHC_3BB0A8C1_0x0051101C | 0.0% | Pending -SHC_3BB0A8C1_0x00511020 | 0.0% | Pending +SHC_3BB0A8C1_0x00511020 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x005110B0 | 0.0% | Pending +SHC_3BB0A8C1_0x005110B0 | 84.0% | moat scan regalloc -SHC_3BB0A8C1_0x005111D0 | 0.0% | Pending +SHC_3BB0A8C1_0x005111D0 | 48.8% | global instance access SHC_3BB0A8C1_0x00511240 | 0.0% | Pending -SHC_3BB0A8C1_0x005113F0 | 0.0% | Pending +SHC_3BB0A8C1_0x005113F0 | 54.2% | moat field reload/regalloc -SHC_3BB0A8C1_0x005114C0 | 0.0% | Pending +SHC_3BB0A8C1_0x005114C0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x005115C0 | 0.0% | Pending -SHC_3BB0A8C1_0x005116E0 | 0.0% | Pending +SHC_3BB0A8C1_0x005116E0 | 72.4% | pitch field reload/regalloc -SHC_3BB0A8C1_0x00511850 | 0.0% | Pending +SHC_3BB0A8C1_0x00511850 | 100.0% | Reimplemented SHC_3BB0A8C1_0x005118C0 | 100.0% | Reimplemented @@ -44723,61 +44723,61 @@ SHC_3BB0A8C1_0x00511D60 | 0.0% | Pending SHC_3BB0A8C1_0x00511D64 | 0.0% | Pending -SHC_3BB0A8C1_0x00511D70 | 0.0% | Pending +SHC_3BB0A8C1_0x00511D70 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x00511DF0 | 0.0% | Pending +SHC_3BB0A8C1_0x00511DF0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x005120C0 | 0.0% | Pending -SHC_3BB0A8C1_0x00512100 | 0.0% | Pending +SHC_3BB0A8C1_0x00512100 | 89.0% | global instance access SHC_3BB0A8C1_0x00512180 | 0.0% | Pending -SHC_3BB0A8C1_0x00512450 | 0.0% | Pending +SHC_3BB0A8C1_0x00512450 | 79.2% | global instance access -SHC_3BB0A8C1_0x005127B0 | 0.0% | Pending +SHC_3BB0A8C1_0x005127B0 | 100.0% | Reimplemented SHC_3BB0A8C1_0x005127D0 | 0.0% | Pending SHC_3BB0A8C1_0x00512920 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x00512940 | 0.0% | Pending +SHC_3BB0A8C1_0x00512940 | 76.0% | Od stack slot order differs -SHC_3BB0A8C1_0x00514480 | 0.0% | Pending +SHC_3BB0A8C1_0x00514480 | 100.0% | Reimplemented -SHC_3BB0A8C1_0x00514520 | 0.0% | Pending +SHC_3BB0A8C1_0x00514520 | 75.3% | 75.63% spill order -SHC_3BB0A8C1_0x005146D0 | 0.0% | Pending +SHC_3BB0A8C1_0x005146D0 | 40.4% | 47.46% regalloc SHC_3BB0A8C1_0x00514BC0 | 0.0% | Pending -SHC_3BB0A8C1_0x00514DE0 | 0.0% | Pending +SHC_3BB0A8C1_0x00514DE0 | 95.2% | was uncompilable; rebuilt tile -SHC_3BB0A8C1_0x00514F30 | 0.0% | Pending +SHC_3BB0A8C1_0x00514F30 | 87.7% | was uncompilable; 16-bit store -SHC_3BB0A8C1_0x005151C0 | 0.0% | Pending +SHC_3BB0A8C1_0x005151C0 | 73.5% | was uncompilable; 16-bit store SHC_3BB0A8C1_0x00515250 | 0.0% | Pending -SHC_3BB0A8C1_0x005154D0 | 0.0% | Pending +SHC_3BB0A8C1_0x005154D0 | 84.0% | was uncompilable; 16-bit store SHC_3BB0A8C1_0x005155E0 | 0.0% | Pending SHC_3BB0A8C1_0x00515680 | 0.0% | Pending -SHC_3BB0A8C1_0x00515740 | 0.0% | Pending +SHC_3BB0A8C1_0x00515740 | 69.2% | was uncompilable; rebuilt tile -SHC_3BB0A8C1_0x00515A20 | 0.0% | Pending +SHC_3BB0A8C1_0x00515A20 | 34.1% | 54.84% x/y regalloc swap -SHC_3BB0A8C1_0x00515C80 | 0.0% | Pending +SHC_3BB0A8C1_0x00515C80 | 52.6% | ecx not kept across callee -SHC_3BB0A8C1_0x00515DA0 | 0.0% | Pending +SHC_3BB0A8C1_0x00515DA0 | 36.1% | brush loop regalloc -SHC_3BB0A8C1_0x00515F40 | 0.0% | Pending +SHC_3BB0A8C1_0x00515F40 | 69.9% | Style pass, asm differs -SHC_3BB0A8C1_0x005160C0 | 0.0% | Pending +SHC_3BB0A8C1_0x005160C0 | 49.5% | global instance access -SHC_3BB0A8C1_0x005162D0 | 0.0% | Pending +SHC_3BB0A8C1_0x005162D0 | 41.9% | was uncompilable; signature an SHC_3BB0A8C1_0x00516A64 | 0.0% | Pending @@ -45133,7 +45133,7 @@ SHC_3BB0A8C1_0x00516B73 | 0.0% | Pending SHC_3BB0A8C1_0x00516B74 | 0.0% | Pending -SHC_3BB0A8C1_0x00516B80 | 0.0% | Pending +SHC_3BB0A8C1_0x00516B80 | 46.0% | 47.86% four labels as flags SHC_3BB0A8C1_0x005176C8 | 0.0% | Pending @@ -45435,7 +45435,7 @@ SHC_3BB0A8C1_0x00517789 | 0.0% | Pending SHC_3BB0A8C1_0x0051778A | 0.0% | Pending -SHC_3BB0A8C1_0x00517790 | 0.0% | Pending +SHC_3BB0A8C1_0x00517790 | 48.0% | int locals for short field rea SHC_3BB0A8C1_0x00518068 | 0.0% | Pending