1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2025-12-23 15:52:55 +01:00

Fix #9719: Hacked walls in RCT1 saves are imported incorrectly (#11222)

This commit is contained in:
Michael Steenbeek
2020-04-05 13:49:36 +02:00
committed by GitHub
parent 1199295099
commit 8a12ad8f6b
9 changed files with 221 additions and 204 deletions

View File

@@ -5,6 +5,7 @@
- Fix: [#475] Water sides drawn incorrectly (original bug). - Fix: [#475] Water sides drawn incorrectly (original bug).
- Fix: [#6123, #7907, #9472, #11028] Cannot build some track designs with 4 stations (original bug). - Fix: [#6123, #7907, #9472, #11028] Cannot build some track designs with 4 stations (original bug).
- Fix: [#7094] Back wall edge texture in water missing. - Fix: [#7094] Back wall edge texture in water missing.
- Fix: [#9719] Hacked walls in RCT1 saves are imported incorrectly.
- Fix: [#10928] File browser's date column is too narrow. - Fix: [#10928] File browser's date column is too narrow.
- Fix: [#10951, #11160] Attempting to place park entrances creates ghost entrances in random locations. - Fix: [#10951, #11160] Attempting to place park entrances creates ghost entrances in random locations.
- Fix: [#11005] Company value overflows. - Fix: [#11005] Company value overflows.

View File

@@ -21,6 +21,7 @@
#include "../world/Scenery.h" #include "../world/Scenery.h"
#include "../world/SmallScenery.h" #include "../world/SmallScenery.h"
#include "../world/Surface.h" #include "../world/Surface.h"
#include "../world/Wall.h"
#include "GameAction.h" #include "GameAction.h"
class WallPlaceActionResult final : public GameActionResult class WallPlaceActionResult final : public GameActionResult
@@ -150,7 +151,7 @@ public:
targetHeight = surfaceElement->GetBaseZ(); targetHeight = surfaceElement->GetBaseZ();
uint8_t slope = surfaceElement->GetSlope(); uint8_t slope = surfaceElement->GetSlope();
edgeSlope = EdgeSlopes[slope][_edge & 3]; edgeSlope = LandSlopeToWallSlope[slope][_edge & 3];
if (edgeSlope & EDGE_SLOPE_ELEVATED) if (edgeSlope & EDGE_SLOPE_ELEVATED)
{ {
targetHeight += 16; targetHeight += 16;
@@ -324,7 +325,7 @@ public:
targetHeight = surfaceElement->GetBaseZ(); targetHeight = surfaceElement->GetBaseZ();
uint8_t slope = surfaceElement->GetSlope(); uint8_t slope = surfaceElement->GetSlope();
edgeSlope = EdgeSlopes[slope][_edge & 3]; edgeSlope = LandSlopeToWallSlope[slope][_edge & 3];
if (edgeSlope & EDGE_SLOPE_ELEVATED) if (edgeSlope & EDGE_SLOPE_ELEVATED)
{ {
targetHeight += 16; targetHeight += 16;
@@ -401,8 +402,7 @@ public:
WallElement* wallElement = tileElement->AsWall(); WallElement* wallElement = tileElement->AsWall();
wallElement->clearance_height = clearanceHeight; wallElement->clearance_height = clearanceHeight;
wallElement->SetDirection(_edge); wallElement->SetDirection(_edge);
// TODO: Normalise the edge slope code. wallElement->SetSlope(edgeSlope);
wallElement->SetSlope(edgeSlope >> 6);
wallElement->SetPrimaryColour(_primaryColour); wallElement->SetPrimaryColour(_primaryColour);
wallElement->SetSecondaryColour(_secondaryColour); wallElement->SetSecondaryColour(_secondaryColour);
@@ -436,59 +436,6 @@ public:
} }
private: private:
#pragma region Edge Slopes Table
// clang-format off
enum EDGE_SLOPE
{
EDGE_SLOPE_ELEVATED = (1 << 0), // 0x01
EDGE_SLOPE_UPWARDS = (1 << 6), // 0x40
EDGE_SLOPE_DOWNWARDS = (1 << 7), // 0x80
EDGE_SLOPE_UPWARDS_ELEVATED = EDGE_SLOPE_UPWARDS | EDGE_SLOPE_ELEVATED,
EDGE_SLOPE_DOWNWARDS_ELEVATED = EDGE_SLOPE_DOWNWARDS | EDGE_SLOPE_ELEVATED,
};
/** rct2: 0x009A3FEC */
static constexpr const uint8_t EdgeSlopes[][4] = {
// Top right Bottom right Bottom left Top left
{ 0, 0, 0, 0 },
{ 0, EDGE_SLOPE_UPWARDS, EDGE_SLOPE_DOWNWARDS, 0 },
{ 0, 0, EDGE_SLOPE_UPWARDS, EDGE_SLOPE_DOWNWARDS },
{ 0, EDGE_SLOPE_UPWARDS, EDGE_SLOPE_ELEVATED, EDGE_SLOPE_DOWNWARDS },
{ EDGE_SLOPE_DOWNWARDS, 0, 0, EDGE_SLOPE_UPWARDS },
{ EDGE_SLOPE_DOWNWARDS, EDGE_SLOPE_UPWARDS, EDGE_SLOPE_DOWNWARDS, EDGE_SLOPE_UPWARDS },
{ EDGE_SLOPE_DOWNWARDS, 0, EDGE_SLOPE_UPWARDS, EDGE_SLOPE_ELEVATED },
{ EDGE_SLOPE_DOWNWARDS, EDGE_SLOPE_UPWARDS, EDGE_SLOPE_ELEVATED, EDGE_SLOPE_ELEVATED },
{ EDGE_SLOPE_UPWARDS, EDGE_SLOPE_DOWNWARDS, 0, 0 },
{ EDGE_SLOPE_UPWARDS, EDGE_SLOPE_ELEVATED, EDGE_SLOPE_DOWNWARDS, 0 },
{ EDGE_SLOPE_UPWARDS, EDGE_SLOPE_DOWNWARDS, EDGE_SLOPE_UPWARDS, EDGE_SLOPE_DOWNWARDS },
{ EDGE_SLOPE_UPWARDS, EDGE_SLOPE_ELEVATED, EDGE_SLOPE_ELEVATED, EDGE_SLOPE_DOWNWARDS },
{ EDGE_SLOPE_ELEVATED, EDGE_SLOPE_DOWNWARDS, 0, EDGE_SLOPE_UPWARDS },
{ EDGE_SLOPE_ELEVATED, EDGE_SLOPE_ELEVATED, EDGE_SLOPE_DOWNWARDS, EDGE_SLOPE_UPWARDS },
{ EDGE_SLOPE_ELEVATED, EDGE_SLOPE_DOWNWARDS, EDGE_SLOPE_UPWARDS, EDGE_SLOPE_ELEVATED },
{ EDGE_SLOPE_ELEVATED, EDGE_SLOPE_ELEVATED, EDGE_SLOPE_ELEVATED, EDGE_SLOPE_ELEVATED },
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 },
{ EDGE_SLOPE_DOWNWARDS, EDGE_SLOPE_UPWARDS, EDGE_SLOPE_UPWARDS_ELEVATED, EDGE_SLOPE_DOWNWARDS_ELEVATED },
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 },
{ EDGE_SLOPE_UPWARDS, EDGE_SLOPE_UPWARDS_ELEVATED, EDGE_SLOPE_DOWNWARDS_ELEVATED, EDGE_SLOPE_DOWNWARDS },
{ 0, 0, 0, 0 },
{ EDGE_SLOPE_UPWARDS_ELEVATED, EDGE_SLOPE_DOWNWARDS_ELEVATED, EDGE_SLOPE_DOWNWARDS, EDGE_SLOPE_UPWARDS },
{ EDGE_SLOPE_DOWNWARDS_ELEVATED, EDGE_SLOPE_DOWNWARDS, EDGE_SLOPE_UPWARDS, EDGE_SLOPE_UPWARDS_ELEVATED },
{ 0, 0, 0, 0 },
};
// clang-format on
#pragma endregion
/** /**
* *
* rct2: 0x006E5CBA * rct2: 0x006E5CBA

View File

@@ -1055,19 +1055,58 @@ enum
enum enum
{ {
RCT1_WALL_TYPE_MESH_FENCE = 0,
RCT1_WALL_TYPE_MESH_FENCE_WITH_GATE = 1,
RCT1_WALL_TYPE_ROMAN = 2,
RCT1_WALL_TYPE_EGYPTIAN = 3,
RCT1_WALL_TYPE_HEDGE = 4,
RCT1_WALL_TYPE_HEDGE_WITH_GATE = 5,
RCT1_WALL_TYPE_BLUE_PLAYING_CARDS = 6,
RCT1_WALL_TYPE_RED_PLAYING_CARDS = 7,
RCT1_WALL_TYPE_WHITE_RAILING = 8,
RCT1_WALL_TYPE_WHITE_RAILING_WITH_GATE = 9,
RCT1_WALL_TYPE_MARTIAN = 10,
RCT1_WALL_TYPE_GLASS_SMOOTH = 11, RCT1_WALL_TYPE_GLASS_SMOOTH = 11,
RCT1_WALL_TYPE_GLASS_PANELS = 22,
RCT1_WALL_TYPE_WOODEN_PANEL_FENCE = 12, RCT1_WALL_TYPE_WOODEN_PANEL_FENCE = 12,
RCT1_WALL_TYPE_WOODEN_PANEL_FENCE_WITH_GATE = 13, RCT1_WALL_TYPE_WOODEN_PANEL_FENCE_WITH_GATE = 13,
RCT1_WALL_TYPE_WOODEN_POST_FENCE = 14,
RCT1_WALL_TYPE_RED_WOODEN_POST_FENCE = 15,
RCT1_WALL_TYPE_BARBED_WIRE = 16,
RCT1_WALL_TYPE_BARBED_WIRE_WITH_GATE = 17,
RCT1_WALL_TYPE_PRIMITIVE_TALL_WOOD_FENCE = 18,
RCT1_WALL_TYPE_PRIMITIVE_SHORT_WOOD_FENCE = 19,
RCT1_WALL_TYPE_IRON_RAILING = 20,
RCT1_WALL_TYPE_IRON_RAILING_WITH_GATE = 21,
RCT1_WALL_TYPE_GLASS_PANELS = 22,
RCT1_WALL_TYPE_BONE_FENCE = 23,
RCT1_WALL_TYPE_BRICK = 24,
RCT1_WALL_TYPE_BRICK_WITH_GATE = 25,
RCT1_WALL_TYPE_WHITE_WOODEN_PANEL_FENCE = 26, RCT1_WALL_TYPE_WHITE_WOODEN_PANEL_FENCE = 26,
RCT1_WALL_TYPE_RED_WOODEN_PANEL_FENCE = 27, RCT1_WALL_TYPE_RED_WOODEN_PANEL_FENCE = 27,
RCT1_WALL_TYPE_STONE = 28,
RCT1_WALL_TYPE_STONE_WITH_GATE = 29,
RCT1_WALL_TYPE_WOODEN_FENCE = 30,
RCT1_WALL_TYPE_JUNGLE = 31,
RCT1_WALL_TYPE_CONIFER_HEDGE = 32,
RCT1_WALL_TYPE_CONIFER_HEDGE_WITH_GATE = 33,
RCT1_WALL_TYPE_SMALL_BROWN_CASTLE = 34,
RCT1_WALL_TYPE_SMALL_GREY_CASTLE = 35, RCT1_WALL_TYPE_SMALL_GREY_CASTLE = 35,
RCT1_WALL_TYPE_LARGE_CREY_CASTLE = 42, RCT1_WALL_TYPE_ROMAN_COLUMN = 36,
RCT1_WALL_TYPE_LARGE_CREY_CASTLE_CROSS = 43, RCT1_WALL_TYPE_LARGE_BROWN_CASTLE = 37,
RCT1_WALL_TYPE_LARGE_CREY_CASTLE_GATE = 44, RCT1_WALL_TYPE_LARGE_BROWN_CASTLE_CROSS = 38,
RCT1_WALL_TYPE_LARGE_CREY_CASTLE_WINDOW = 45, RCT1_WALL_TYPE_LARGE_BROWN_CASTLE_GATE = 39,
RCT1_WALL_TYPE_MEDIUM_CREY_CASTLE = 46, RCT1_WALL_TYPE_LARGE_BROWN_CASTLE_WINDOW = 40,
RCT1_WALL_TYPE_MEDIUM_BROWN_CASTLE = 41,
RCT1_WALL_TYPE_LARGE_GREY_CASTLE = 42,
RCT1_WALL_TYPE_LARGE_GREY_CASTLE_CROSS = 43,
RCT1_WALL_TYPE_LARGE_GREY_CASTLE_GATE = 44,
RCT1_WALL_TYPE_LARGE_GREY_CASTLE_WINDOW = 45,
RCT1_WALL_TYPE_MEDIUM_GREY_CASTLE = 46,
RCT1_WALL_TYPE_CREEPY = 47,
RCT1_WALL_TYPE_CREEPY_GATE = 48,
RCT1_WALL_TYPE_BARBED_WIRE_WITH_SNOW = 49,
RCT1_WALL_TYPE_WOODEN_PANEL_FENCE_WITH_SNOW = 50, RCT1_WALL_TYPE_WOODEN_PANEL_FENCE_WITH_SNOW = 50,
RCT1_WALL_TYPE_WOODEN_POST_FENCE_WITH_SNOW = 51,
}; };
enum enum

View File

@@ -51,6 +51,7 @@
#include "../world/Scenery.h" #include "../world/Scenery.h"
#include "../world/SmallScenery.h" #include "../world/SmallScenery.h"
#include "../world/Surface.h" #include "../world/Surface.h"
#include "../world/Wall.h"
#include "RCT1.h" #include "RCT1.h"
#include "Tables.h" #include "Tables.h"
@@ -1991,7 +1992,7 @@ private:
// All saved in "flags" // All saved in "flags"
dst->SetOccupiedQuadrants(src->GetOccupiedQuadrants()); dst->SetOccupiedQuadrants(src->GetOccupiedQuadrants());
dst->SetGhost(src->IsGhost()); // Skipping IsGhost, which appears to use a different flag in RCT1.
dst->SetLastForTile(src->IsLastForTile()); dst->SetLastForTile(src->IsLastForTile());
dst->SetBaseZ(src->base_height * RCT1_COORDS_Z_STEP); dst->SetBaseZ(src->base_height * RCT1_COORDS_Z_STEP);
@@ -2187,9 +2188,7 @@ private:
auto dst2 = dst->AsWall(); auto dst2 = dst->AsWall();
auto src2 = src->AsWall(); auto src2 = src->AsWall();
dst2->SetEntryIndex(src2->GetEntryIndex());
dst2->SetSlope(src2->GetSlope()); dst2->SetSlope(src2->GetSlope());
dst2->SetPrimaryColour(RCT1::GetColour(src2->GetRCT1WallColour()));
dst2->SetRawRCT1Data(src2->GetRawRCT1WallTypeData()); dst2->SetRawRCT1Data(src2->GetRawRCT1WallTypeData());
break; break;
@@ -2763,10 +2762,7 @@ private:
void FixWalls() void FixWalls()
{ {
// The user might attempt to load a save while in pause mode. std::vector<TileElement> wallsOnTile = {};
// Since we cannot place walls in pause mode without a cheat, temporarily turn it on.
bool oldCheatValue = gCheatsBuildInPauseMode;
gCheatsBuildInPauseMode = true;
for (int32_t x = 0; x < RCT1_MAX_MAP_SIZE; x++) for (int32_t x = 0; x < RCT1_MAX_MAP_SIZE; x++)
{ {
@@ -2779,40 +2775,55 @@ private:
{ {
if (tileElement->GetType() == TILE_ELEMENT_TYPE_WALL) if (tileElement->GetType() == TILE_ELEMENT_TYPE_WALL)
{ {
TileElement originalTileElement = *tileElement; wallsOnTile.push_back(*tileElement);
tile_element_remove(tileElement); tile_element_remove(tileElement);
tileElement--;
}
} while (!(tileElement++)->IsLastForTile());
for (auto originalTileElement : wallsOnTile)
{
auto location = TileCoordsXYZ(x, y, 0).ToCoordsXYZ();
for (int32_t edge = 0; edge < 4; edge++) for (int32_t edge = 0; edge < 4; edge++)
{ {
int32_t type = originalTileElement.AsWall()->GetRCT1WallType(edge); int32_t type = originalTileElement.AsWall()->GetRCT1WallType(edge);
auto slope = originalTileElement.AsWall()->GetRCT1Slope();
if (type != -1) if (type != -1)
{ {
int32_t colourA = RCT1::GetColour(originalTileElement.AsWall()->GetRCT1WallColour()); colour_t colourA = RCT1::GetColour(originalTileElement.AsWall()->GetRCT1WallColour());
int32_t colourB = 0; colour_t colourB = COLOUR_BLACK;
int32_t colourC = 0; colour_t colourC = COLOUR_BLACK;
ConvertWall(&type, &colourA, &colourB); ConvertWall(&type, &colourA, &colourB);
type = _wallTypeToEntryMap[type]; type = _wallTypeToEntryMap[type];
auto edgeSlope = LandSlopeToWallSlope[slope][edge & 3] & ~EDGE_SLOPE_ELEVATED;
auto location = TileCoordsXYZ(x, y, 0).ToCoordsXYZ(); auto element = tile_element_insert(location, originalTileElement.GetOccupiedQuadrants());
auto wallPlaceAction = WallPlaceAction(type, location, edge, colourA, colourB, colourC); element->SetType(TILE_ELEMENT_TYPE_WALL);
wallPlaceAction.SetFlags( element->SetDirection(edge);
GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED | GAME_COMMAND_FLAG_NO_SPEND element->SetBaseZ(originalTileElement.GetBaseZ());
| GAME_COMMAND_FLAG_PATH_SCENERY); element->SetClearanceZ(originalTileElement.GetClearanceZ());
GameActions::Execute(&wallPlaceAction);
auto wallElement = element->AsWall();
wallElement->SetEntryIndex(type);
wallElement->SetPrimaryColour(colourA);
wallElement->SetSecondaryColour(colourB);
wallElement->SetTertiaryColour(colourC);
wallElement->SetBannerIndex(BANNER_INDEX_NULL);
wallElement->SetAcrossTrack(originalTileElement.AsWall()->IsAcrossTrack());
wallElement->SetAnimationIsBackwards(originalTileElement.AsWall()->AnimationIsBackwards());
wallElement->SetSlope(edgeSlope);
} }
} }
break;
} }
} while (!(tileElement++)->IsLastForTile()); wallsOnTile.clear();
}
} }
} }
gCheatsBuildInPauseMode = oldCheatValue; void ConvertWall(int32_t* type, colour_t* colourA, colour_t* colourB)
}
void ConvertWall(int32_t* type, int32_t* colourA, int32_t* colourB)
{ {
switch (*type) switch (*type)
{ {
@@ -2837,11 +2848,11 @@ private:
*colourB = COLOUR_WHITE; *colourB = COLOUR_WHITE;
break; break;
case RCT1_WALL_TYPE_SMALL_GREY_CASTLE: case RCT1_WALL_TYPE_SMALL_GREY_CASTLE:
case RCT1_WALL_TYPE_LARGE_CREY_CASTLE: case RCT1_WALL_TYPE_LARGE_GREY_CASTLE:
case RCT1_WALL_TYPE_LARGE_CREY_CASTLE_CROSS: case RCT1_WALL_TYPE_LARGE_GREY_CASTLE_CROSS:
case RCT1_WALL_TYPE_LARGE_CREY_CASTLE_GATE: case RCT1_WALL_TYPE_LARGE_GREY_CASTLE_GATE:
case RCT1_WALL_TYPE_LARGE_CREY_CASTLE_WINDOW: case RCT1_WALL_TYPE_LARGE_GREY_CASTLE_WINDOW:
case RCT1_WALL_TYPE_MEDIUM_CREY_CASTLE: case RCT1_WALL_TYPE_MEDIUM_GREY_CASTLE:
*colourA = COLOUR_GREY; *colourA = COLOUR_GREY;
break; break;
} }
@@ -3118,5 +3129,5 @@ int32_t WallElement::GetRCT1WallType(int32_t edge) const
colour_t WallElement::GetRCT1WallColour() const colour_t WallElement::GetRCT1WallColour() const
{ {
return ((type & 0xC0) >> 3) | ((entryIndex & 0xE0) >> 5); return (((type & 0xC0) >> 3) | ((entryIndex & 0xE0) >> 5)) & 31;
} }

View File

@@ -1177,104 +1177,63 @@ namespace RCT1
{ {
static constexpr const char * map[] = static constexpr const char * map[] =
{ {
"WMF ", "WMF ", // RCT1_WALL_TYPE_MESH_FENCE
"WMFG ", "WMFG ", // RCT1_WALL_TYPE_MESH_FENCE_WITH_GATE
"WRW ", "WRW ", // RCT1_WALL_TYPE_ROMAN
"WEW ", "WEW ", // RCT1_WALL_TYPE_EGYPTIAN
"WHG ", "WHG ", // RCT1_WALL_TYPE_HEDGE
"WHGG ", "WHGG ", // RCT1_WALL_TYPE_HEDGE_WITH_GATE
"WCW1 ", "WCW1 ", // RCT1_WALL_TYPE_BLUE_PLAYING_CARDS
"WCW2 ", "WCW2 ", // RCT1_WALL_TYPE_RED_PLAYING_CARDS
"WSW ", "WSW ", // RCT1_WALL_TYPE_WHITE_RAILING
"WSWG ", "WSWG ", // RCT1_WALL_TYPE_WHITE_RAILING_WITH_GATE
"WMW ", "WMW ", // RCT1_WALL_TYPE_MARTIAN
"WALLGL16", "WALLGL16", // RCT1_WALL_TYPE_GLASS_SMOOTH
"WFW1 ", "WFW1 ", // RCT1_WALL_TYPE_WOODEN_PANEL_FENCE
"WFWG ", "WFWG ", // RCT1_WALL_TYPE_WOODEN_PANEL_FENCE_WITH_GATE
"WPW1 ", "WPW1 ", // RCT1_WALL_TYPE_WOODEN_POST_FENCE
"WPW2 ", "WPW2 ", // RCT1_WALL_TYPE_RED_WOODEN_POST_FENCE
"WPF ", "WPF ", // RCT1_WALL_TYPE_BARBED_WIRE
"WPFG ", "WPFG ", // RCT1_WALL_TYPE_BARBED_WIRE_WITH_GATE
"WWTW ", "WWTW ", // RCT1_WALL_TYPE_PRIMITIVE_TALL_WOOD_FENCE
"WMWW ", "WMWW ", // RCT1_WALL_TYPE_PRIMITIVE_SHORT_WOOD_FENCE
"WSW1 ", "WSW1 ", // RCT1_WALL_TYPE_IRON_RAILING
"WSW2 ", "WSW2 ", // RCT1_WALL_TYPE_IRON_RAILING_WITH_GATE
"WGW2 ", "WGW2 ", // RCT1_WALL_TYPE_GLASS_PANELS
"WBW ", "WBW ", // RCT1_WALL_TYPE_BONE_FENCE
"WBR1 ", "WBR1 ", // RCT1_WALL_TYPE_BRICK
"WBRG ", "WBRG ", // RCT1_WALL_TYPE_BRICK_WITH_GATE
"WFW1 ", "WFW1 ", // RCT1_WALL_TYPE_WHITE_WOODEN_PANEL_FENCE
"WFW1 ", "WFW1 ", // RCT1_WALL_TYPE_RED_WOODEN_PANEL_FENCE
"WBR2 ", "WBR2 ", // RCT1_WALL_TYPE_STONE
"WBR3 ", "WBR3 ", // RCT1_WALL_TYPE_STONE_WITH_GATE
"WPW3 ", "WPW3 ", // RCT1_WALL_TYPE_WOODEN_FENCE
"WJF ", "WJF ", // RCT1_WALL_TYPE_JUNGLE
"WCH ", "WCH ", // RCT1_WALL_TYPE_CONIFER_HEDGE
"WCHG ", "WCHG ", // RCT1_WALL_TYPE_CONIFER_HEDGE_WITH_GATE
"WC1 ", "WC1 ", // RCT1_WALL_TYPE_SMALL_BROWN_CASTLE
"WC2 ", "WC2 ", // RCT1_WALL_TYPE_SMALL_GREY_CASTLE
"WC3 ", "WC3 ", // RCT1_WALL_TYPE_ROMAN_COLUMN
"WC4 ", "WC4 ", // RCT1_WALL_TYPE_LARGE_BROWN_CASTLE
"WC5 ", "WC5 ", // RCT1_WALL_TYPE_LARGE_BROWN_CASTLE_CROSS
"WC6 ", "WC6 ", // RCT1_WALL_TYPE_LARGE_BROWN_CASTLE_GATE
"WC7 ", "WC7 ", // RCT1_WALL_TYPE_LARGE_BROWN_CASTLE_WINDOW
"WC8 ", "WC8 ", // RCT1_WALL_TYPE_MEDIUM_BROWN_CASTLE
"WC9 ", "WC9 ", // RCT1_WALL_TYPE_LARGE_GREY_CASTLE
"WC10 ", "WC10 ", // RCT1_WALL_TYPE_LARGE_GREY_CASTLE_CROSS
"WC11 ", "WC11 ", // RCT1_WALL_TYPE_LARGE_GREY_CASTLE_GATE
"WC12 ", "WC12 ", // RCT1_WALL_TYPE_LARGE_GREY_CASTLE_WINDOW
"WC13 ", "WC13 ", // RCT1_WALL_TYPE_MEDIUM_GREY_CASTLE
"WC14 ", "WC14 ", // RCT1_WALL_TYPE_CREEPY
"WC15 ", "WC15 ", // RCT1_WALL_TYPE_CREEPY_GATE
"WC16 ", "WC16 ", // RCT1_WALL_TYPE_BARBED_WIRE_WITH_SNOW
"WC17 ", "WC17 ", // RCT1_WALL_TYPE_WOODEN_PANEL_FENCE_WITH_SNOW
"WC18 ", "WC18 ", // RCT1_WALL_TYPE_WOODEN_POST_FENCE_WITH_SNOW
"WALLBRDR",
"WALLBR32",
"WALLBR16",
"WALLBR8 ",
"WALLCF8 ",
"WALLCF16",
"WALLCF32",
"WALLBB8 ",
"WALLBB16",
"WALLBB32",
"WALLRS8 ",
"WALLRS16",
"WALLRS32",
"WALLCB8 ",
"WALLCB16",
"WALLCB32",
"WALLGL8 ",
"WALLGL32",
"WALLWD8 ",
"WALLWD16",
"WALLWD32",
"WALLTN32",
"WALLJN32",
"WALLMN32",
"WALLSP32",
"WALLPG32",
"WALLU132",
"WALLU232",
"WALLCZ32",
"WALLCW32",
"WALLCY32",
"WALLCX32",
"WBR1A ",
"WBR2A ",
"WRWA ",
"WWTWA ",
"WALLIG16",
"WALLIG24",
"WALLCO16",
"WALLCFDR",
"WALLCBDR",
"WALLBRWN",
"WALLCFWN",
"WALLCBWN",
}; };
if (wallType < std::size(map))
return map[wallType]; return map[wallType];
else
return map[0];
} }
const char * GetPathObject(uint8_t pathType) const char * GetPathObject(uint8_t pathType)

View File

@@ -410,7 +410,7 @@ bool RCT12WallElement::AnimationIsBackwards() const
uint32_t RCT12WallElement::GetRawRCT1WallTypeData() const uint32_t RCT12WallElement::GetRawRCT1WallTypeData() const
{ {
return colour_3 | (colour_1 << 8) | (animation << 16); return entryIndex | (colour_3 << 8) | (colour_1 << 16) | (animation << 24);
} }
int32_t RCT12WallElement::GetRCT1WallType(int32_t edge) const int32_t RCT12WallElement::GetRCT1WallType(int32_t edge) const

View File

@@ -480,6 +480,7 @@ public:
void SetRawRCT1Data(uint32_t rawData); void SetRawRCT1Data(uint32_t rawData);
int32_t GetRCT1WallType(int32_t edge) const; int32_t GetRCT1WallType(int32_t edge) const;
colour_t GetRCT1WallColour() const; colour_t GetRCT1WallColour() const;
uint8_t GetRCT1Slope() const;
}; };
assert_struct_size(WallElement, 16); assert_struct_size(WallElement, 16);

View File

@@ -203,7 +203,13 @@ void WallElement::SetAnimationIsBackwards(bool isBackwards)
void WallElement::SetRawRCT1Data(uint32_t rawData) void WallElement::SetRawRCT1Data(uint32_t rawData)
{ {
colour_3 = rawData & 0xFF; entryIndex = rawData & 0xFF;
colour_1 = (rawData >> 8) & 0xFF; colour_3 = (rawData >> 8) & 0xFF;
animation = (rawData >> 16) & 0xFF; colour_1 = (rawData >> 16) & 0xFF;
animation = (rawData >> 24) & 0xFF;
}
uint8_t WallElement::GetRCT1Slope() const
{
return entryIndex & 0b00011111;
} }

View File

@@ -20,4 +20,57 @@ enum
WALL_ANIMATION_FLAG_ALL_FLAGS = WALL_ANIMATION_FLAG_ACROSS_TRACK | WALL_ANIMATION_FLAG_DIRECTION_BACKWARD WALL_ANIMATION_FLAG_ALL_FLAGS = WALL_ANIMATION_FLAG_ACROSS_TRACK | WALL_ANIMATION_FLAG_DIRECTION_BACKWARD
}; };
#pragma region Edge Slopes Table
// clang-format off
enum EDGE_SLOPE
{
EDGE_SLOPE_UPWARDS = (1 << 0),
EDGE_SLOPE_DOWNWARDS = (1 << 1),
EDGE_SLOPE_ELEVATED = (1 << 2),
EDGE_SLOPE_UPWARDS_ELEVATED = EDGE_SLOPE_UPWARDS | EDGE_SLOPE_ELEVATED,
EDGE_SLOPE_DOWNWARDS_ELEVATED = EDGE_SLOPE_DOWNWARDS | EDGE_SLOPE_ELEVATED,
};
/** rct2: 0x009A3FEC */
constexpr const uint8_t LandSlopeToWallSlope[][NumOrthogonalDirections] = {
// Top right Bottom right Bottom left Top left
{ 0, 0, 0, 0 },
{ 0, EDGE_SLOPE_UPWARDS, EDGE_SLOPE_DOWNWARDS, 0 },
{ 0, 0, EDGE_SLOPE_UPWARDS, EDGE_SLOPE_DOWNWARDS },
{ 0, EDGE_SLOPE_UPWARDS, EDGE_SLOPE_ELEVATED, EDGE_SLOPE_DOWNWARDS },
{ EDGE_SLOPE_DOWNWARDS, 0, 0, EDGE_SLOPE_UPWARDS },
{ EDGE_SLOPE_DOWNWARDS, EDGE_SLOPE_UPWARDS, EDGE_SLOPE_DOWNWARDS, EDGE_SLOPE_UPWARDS },
{ EDGE_SLOPE_DOWNWARDS, 0, EDGE_SLOPE_UPWARDS, EDGE_SLOPE_ELEVATED },
{ EDGE_SLOPE_DOWNWARDS, EDGE_SLOPE_UPWARDS, EDGE_SLOPE_ELEVATED, EDGE_SLOPE_ELEVATED },
{ EDGE_SLOPE_UPWARDS, EDGE_SLOPE_DOWNWARDS, 0, 0 },
{ EDGE_SLOPE_UPWARDS, EDGE_SLOPE_ELEVATED, EDGE_SLOPE_DOWNWARDS, 0 },
{ EDGE_SLOPE_UPWARDS, EDGE_SLOPE_DOWNWARDS, EDGE_SLOPE_UPWARDS, EDGE_SLOPE_DOWNWARDS },
{ EDGE_SLOPE_UPWARDS, EDGE_SLOPE_ELEVATED, EDGE_SLOPE_ELEVATED, EDGE_SLOPE_DOWNWARDS },
{ EDGE_SLOPE_ELEVATED, EDGE_SLOPE_DOWNWARDS, 0, EDGE_SLOPE_UPWARDS },
{ EDGE_SLOPE_ELEVATED, EDGE_SLOPE_ELEVATED, EDGE_SLOPE_DOWNWARDS, EDGE_SLOPE_UPWARDS },
{ EDGE_SLOPE_ELEVATED, EDGE_SLOPE_DOWNWARDS, EDGE_SLOPE_UPWARDS, EDGE_SLOPE_ELEVATED },
{ EDGE_SLOPE_ELEVATED, EDGE_SLOPE_ELEVATED, EDGE_SLOPE_ELEVATED, EDGE_SLOPE_ELEVATED },
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 },
{ EDGE_SLOPE_DOWNWARDS, EDGE_SLOPE_UPWARDS, EDGE_SLOPE_UPWARDS_ELEVATED, EDGE_SLOPE_DOWNWARDS_ELEVATED },
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 },
{ EDGE_SLOPE_UPWARDS, EDGE_SLOPE_UPWARDS_ELEVATED, EDGE_SLOPE_DOWNWARDS_ELEVATED, EDGE_SLOPE_DOWNWARDS },
{ 0, 0, 0, 0 },
{ EDGE_SLOPE_UPWARDS_ELEVATED, EDGE_SLOPE_DOWNWARDS_ELEVATED, EDGE_SLOPE_DOWNWARDS, EDGE_SLOPE_UPWARDS },
{ EDGE_SLOPE_DOWNWARDS_ELEVATED, EDGE_SLOPE_DOWNWARDS, EDGE_SLOPE_UPWARDS, EDGE_SLOPE_UPWARDS_ELEVATED },
{ 0, 0, 0, 0 },
};
// clang-format on
#pragma endregion
money32 wall_remove(int16_t x, int16_t y, uint8_t baseHeight, uint8_t direction, uint8_t flags); money32 wall_remove(int16_t x, int16_t y, uint8_t baseHeight, uint8_t direction, uint8_t flags);