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
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 221 additions and 204 deletions

View File

@ -5,6 +5,7 @@
- Fix: [#475] Water sides drawn incorrectly (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: [#9719] Hacked walls in RCT1 saves are imported incorrectly.
- 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: [#11005] Company value overflows.

View File

@ -21,6 +21,7 @@
#include "../world/Scenery.h"
#include "../world/SmallScenery.h"
#include "../world/Surface.h"
#include "../world/Wall.h"
#include "GameAction.h"
class WallPlaceActionResult final : public GameActionResult
@ -150,7 +151,7 @@ public:
targetHeight = surfaceElement->GetBaseZ();
uint8_t slope = surfaceElement->GetSlope();
edgeSlope = EdgeSlopes[slope][_edge & 3];
edgeSlope = LandSlopeToWallSlope[slope][_edge & 3];
if (edgeSlope & EDGE_SLOPE_ELEVATED)
{
targetHeight += 16;
@ -324,7 +325,7 @@ public:
targetHeight = surfaceElement->GetBaseZ();
uint8_t slope = surfaceElement->GetSlope();
edgeSlope = EdgeSlopes[slope][_edge & 3];
edgeSlope = LandSlopeToWallSlope[slope][_edge & 3];
if (edgeSlope & EDGE_SLOPE_ELEVATED)
{
targetHeight += 16;
@ -401,8 +402,7 @@ public:
WallElement* wallElement = tileElement->AsWall();
wallElement->clearance_height = clearanceHeight;
wallElement->SetDirection(_edge);
// TODO: Normalise the edge slope code.
wallElement->SetSlope(edgeSlope >> 6);
wallElement->SetSlope(edgeSlope);
wallElement->SetPrimaryColour(_primaryColour);
wallElement->SetSecondaryColour(_secondaryColour);
@ -436,59 +436,6 @@ public:
}
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

View File

@ -1055,19 +1055,58 @@ 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_PANELS = 22,
RCT1_WALL_TYPE_WOODEN_PANEL_FENCE = 12,
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_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_LARGE_CREY_CASTLE = 42,
RCT1_WALL_TYPE_LARGE_CREY_CASTLE_CROSS = 43,
RCT1_WALL_TYPE_LARGE_CREY_CASTLE_GATE = 44,
RCT1_WALL_TYPE_LARGE_CREY_CASTLE_WINDOW = 45,
RCT1_WALL_TYPE_MEDIUM_CREY_CASTLE = 46,
RCT1_WALL_TYPE_ROMAN_COLUMN = 36,
RCT1_WALL_TYPE_LARGE_BROWN_CASTLE = 37,
RCT1_WALL_TYPE_LARGE_BROWN_CASTLE_CROSS = 38,
RCT1_WALL_TYPE_LARGE_BROWN_CASTLE_GATE = 39,
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_POST_FENCE_WITH_SNOW = 51,
};
enum

View File

@ -51,6 +51,7 @@
#include "../world/Scenery.h"
#include "../world/SmallScenery.h"
#include "../world/Surface.h"
#include "../world/Wall.h"
#include "RCT1.h"
#include "Tables.h"
@ -1991,7 +1992,7 @@ private:
// All saved in "flags"
dst->SetOccupiedQuadrants(src->GetOccupiedQuadrants());
dst->SetGhost(src->IsGhost());
// Skipping IsGhost, which appears to use a different flag in RCT1.
dst->SetLastForTile(src->IsLastForTile());
dst->SetBaseZ(src->base_height * RCT1_COORDS_Z_STEP);
@ -2187,9 +2188,7 @@ private:
auto dst2 = dst->AsWall();
auto src2 = src->AsWall();
dst2->SetEntryIndex(src2->GetEntryIndex());
dst2->SetSlope(src2->GetSlope());
dst2->SetPrimaryColour(RCT1::GetColour(src2->GetRCT1WallColour()));
dst2->SetRawRCT1Data(src2->GetRawRCT1WallTypeData());
break;
@ -2763,10 +2762,7 @@ private:
void FixWalls()
{
// The user might attempt to load a save while in pause mode.
// Since we cannot place walls in pause mode without a cheat, temporarily turn it on.
bool oldCheatValue = gCheatsBuildInPauseMode;
gCheatsBuildInPauseMode = true;
std::vector<TileElement> wallsOnTile = {};
for (int32_t x = 0; x < RCT1_MAX_MAP_SIZE; x++)
{
@ -2779,40 +2775,55 @@ private:
{
if (tileElement->GetType() == TILE_ELEMENT_TYPE_WALL)
{
TileElement originalTileElement = *tileElement;
wallsOnTile.push_back(*tileElement);
tile_element_remove(tileElement);
for (int32_t edge = 0; edge < 4; edge++)
{
int32_t type = originalTileElement.AsWall()->GetRCT1WallType(edge);
if (type != -1)
{
int32_t colourA = RCT1::GetColour(originalTileElement.AsWall()->GetRCT1WallColour());
int32_t colourB = 0;
int32_t colourC = 0;
ConvertWall(&type, &colourA, &colourB);
type = _wallTypeToEntryMap[type];
auto location = TileCoordsXYZ(x, y, 0).ToCoordsXYZ();
auto wallPlaceAction = WallPlaceAction(type, location, edge, colourA, colourB, colourC);
wallPlaceAction.SetFlags(
GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED | GAME_COMMAND_FLAG_NO_SPEND
| GAME_COMMAND_FLAG_PATH_SCENERY);
GameActions::Execute(&wallPlaceAction);
}
}
break;
tileElement--;
}
} while (!(tileElement++)->IsLastForTile());
for (auto originalTileElement : wallsOnTile)
{
auto location = TileCoordsXYZ(x, y, 0).ToCoordsXYZ();
for (int32_t edge = 0; edge < 4; edge++)
{
int32_t type = originalTileElement.AsWall()->GetRCT1WallType(edge);
auto slope = originalTileElement.AsWall()->GetRCT1Slope();
if (type != -1)
{
colour_t colourA = RCT1::GetColour(originalTileElement.AsWall()->GetRCT1WallColour());
colour_t colourB = COLOUR_BLACK;
colour_t colourC = COLOUR_BLACK;
ConvertWall(&type, &colourA, &colourB);
type = _wallTypeToEntryMap[type];
auto edgeSlope = LandSlopeToWallSlope[slope][edge & 3] & ~EDGE_SLOPE_ELEVATED;
auto element = tile_element_insert(location, originalTileElement.GetOccupiedQuadrants());
element->SetType(TILE_ELEMENT_TYPE_WALL);
element->SetDirection(edge);
element->SetBaseZ(originalTileElement.GetBaseZ());
element->SetClearanceZ(originalTileElement.GetClearanceZ());
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);
}
}
}
wallsOnTile.clear();
}
}
gCheatsBuildInPauseMode = oldCheatValue;
}
void ConvertWall(int32_t* type, int32_t* colourA, int32_t* colourB)
void ConvertWall(int32_t* type, colour_t* colourA, colour_t* colourB)
{
switch (*type)
{
@ -2837,11 +2848,11 @@ private:
*colourB = COLOUR_WHITE;
break;
case RCT1_WALL_TYPE_SMALL_GREY_CASTLE:
case RCT1_WALL_TYPE_LARGE_CREY_CASTLE:
case RCT1_WALL_TYPE_LARGE_CREY_CASTLE_CROSS:
case RCT1_WALL_TYPE_LARGE_CREY_CASTLE_GATE:
case RCT1_WALL_TYPE_LARGE_CREY_CASTLE_WINDOW:
case RCT1_WALL_TYPE_MEDIUM_CREY_CASTLE:
case RCT1_WALL_TYPE_LARGE_GREY_CASTLE:
case RCT1_WALL_TYPE_LARGE_GREY_CASTLE_CROSS:
case RCT1_WALL_TYPE_LARGE_GREY_CASTLE_GATE:
case RCT1_WALL_TYPE_LARGE_GREY_CASTLE_WINDOW:
case RCT1_WALL_TYPE_MEDIUM_GREY_CASTLE:
*colourA = COLOUR_GREY;
break;
}
@ -3118,5 +3129,5 @@ int32_t WallElement::GetRCT1WallType(int32_t edge) 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[] =
{
"WMF ",
"WMFG ",
"WRW ",
"WEW ",
"WHG ",
"WHGG ",
"WCW1 ",
"WCW2 ",
"WSW ",
"WSWG ",
"WMW ",
"WALLGL16",
"WFW1 ",
"WFWG ",
"WPW1 ",
"WPW2 ",
"WPF ",
"WPFG ",
"WWTW ",
"WMWW ",
"WSW1 ",
"WSW2 ",
"WGW2 ",
"WBW ",
"WBR1 ",
"WBRG ",
"WFW1 ",
"WFW1 ",
"WBR2 ",
"WBR3 ",
"WPW3 ",
"WJF ",
"WCH ",
"WCHG ",
"WC1 ",
"WC2 ",
"WC3 ",
"WC4 ",
"WC5 ",
"WC6 ",
"WC7 ",
"WC8 ",
"WC9 ",
"WC10 ",
"WC11 ",
"WC12 ",
"WC13 ",
"WC14 ",
"WC15 ",
"WC16 ",
"WC17 ",
"WC18 ",
"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",
"WMF ", // RCT1_WALL_TYPE_MESH_FENCE
"WMFG ", // RCT1_WALL_TYPE_MESH_FENCE_WITH_GATE
"WRW ", // RCT1_WALL_TYPE_ROMAN
"WEW ", // RCT1_WALL_TYPE_EGYPTIAN
"WHG ", // RCT1_WALL_TYPE_HEDGE
"WHGG ", // RCT1_WALL_TYPE_HEDGE_WITH_GATE
"WCW1 ", // RCT1_WALL_TYPE_BLUE_PLAYING_CARDS
"WCW2 ", // RCT1_WALL_TYPE_RED_PLAYING_CARDS
"WSW ", // RCT1_WALL_TYPE_WHITE_RAILING
"WSWG ", // RCT1_WALL_TYPE_WHITE_RAILING_WITH_GATE
"WMW ", // RCT1_WALL_TYPE_MARTIAN
"WALLGL16", // RCT1_WALL_TYPE_GLASS_SMOOTH
"WFW1 ", // RCT1_WALL_TYPE_WOODEN_PANEL_FENCE
"WFWG ", // RCT1_WALL_TYPE_WOODEN_PANEL_FENCE_WITH_GATE
"WPW1 ", // RCT1_WALL_TYPE_WOODEN_POST_FENCE
"WPW2 ", // RCT1_WALL_TYPE_RED_WOODEN_POST_FENCE
"WPF ", // RCT1_WALL_TYPE_BARBED_WIRE
"WPFG ", // RCT1_WALL_TYPE_BARBED_WIRE_WITH_GATE
"WWTW ", // RCT1_WALL_TYPE_PRIMITIVE_TALL_WOOD_FENCE
"WMWW ", // RCT1_WALL_TYPE_PRIMITIVE_SHORT_WOOD_FENCE
"WSW1 ", // RCT1_WALL_TYPE_IRON_RAILING
"WSW2 ", // RCT1_WALL_TYPE_IRON_RAILING_WITH_GATE
"WGW2 ", // RCT1_WALL_TYPE_GLASS_PANELS
"WBW ", // RCT1_WALL_TYPE_BONE_FENCE
"WBR1 ", // RCT1_WALL_TYPE_BRICK
"WBRG ", // RCT1_WALL_TYPE_BRICK_WITH_GATE
"WFW1 ", // RCT1_WALL_TYPE_WHITE_WOODEN_PANEL_FENCE
"WFW1 ", // RCT1_WALL_TYPE_RED_WOODEN_PANEL_FENCE
"WBR2 ", // RCT1_WALL_TYPE_STONE
"WBR3 ", // RCT1_WALL_TYPE_STONE_WITH_GATE
"WPW3 ", // RCT1_WALL_TYPE_WOODEN_FENCE
"WJF ", // RCT1_WALL_TYPE_JUNGLE
"WCH ", // RCT1_WALL_TYPE_CONIFER_HEDGE
"WCHG ", // RCT1_WALL_TYPE_CONIFER_HEDGE_WITH_GATE
"WC1 ", // RCT1_WALL_TYPE_SMALL_BROWN_CASTLE
"WC2 ", // RCT1_WALL_TYPE_SMALL_GREY_CASTLE
"WC3 ", // RCT1_WALL_TYPE_ROMAN_COLUMN
"WC4 ", // RCT1_WALL_TYPE_LARGE_BROWN_CASTLE
"WC5 ", // RCT1_WALL_TYPE_LARGE_BROWN_CASTLE_CROSS
"WC6 ", // RCT1_WALL_TYPE_LARGE_BROWN_CASTLE_GATE
"WC7 ", // RCT1_WALL_TYPE_LARGE_BROWN_CASTLE_WINDOW
"WC8 ", // RCT1_WALL_TYPE_MEDIUM_BROWN_CASTLE
"WC9 ", // RCT1_WALL_TYPE_LARGE_GREY_CASTLE
"WC10 ", // RCT1_WALL_TYPE_LARGE_GREY_CASTLE_CROSS
"WC11 ", // RCT1_WALL_TYPE_LARGE_GREY_CASTLE_GATE
"WC12 ", // RCT1_WALL_TYPE_LARGE_GREY_CASTLE_WINDOW
"WC13 ", // RCT1_WALL_TYPE_MEDIUM_GREY_CASTLE
"WC14 ", // RCT1_WALL_TYPE_CREEPY
"WC15 ", // RCT1_WALL_TYPE_CREEPY_GATE
"WC16 ", // RCT1_WALL_TYPE_BARBED_WIRE_WITH_SNOW
"WC17 ", // RCT1_WALL_TYPE_WOODEN_PANEL_FENCE_WITH_SNOW
"WC18 ", // RCT1_WALL_TYPE_WOODEN_POST_FENCE_WITH_SNOW
};
return map[wallType];
if (wallType < std::size(map))
return map[wallType];
else
return map[0];
}
const char * GetPathObject(uint8_t pathType)

View File

@ -410,7 +410,7 @@ bool RCT12WallElement::AnimationIsBackwards() 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

View File

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

View File

@ -203,7 +203,13 @@ void WallElement::SetAnimationIsBackwards(bool isBackwards)
void WallElement::SetRawRCT1Data(uint32_t rawData)
{
colour_3 = rawData & 0xFF;
colour_1 = (rawData >> 8) & 0xFF;
animation = (rawData >> 16) & 0xFF;
entryIndex = rawData & 0xFF;
colour_3 = (rawData >> 8) & 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
};
#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);