diff --git a/distribution/changelog.txt b/distribution/changelog.txt index cb9e7a68bf..a69f5e9181 100644 --- a/distribution/changelog.txt +++ b/distribution/changelog.txt @@ -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. diff --git a/src/openrct2/actions/WallPlaceAction.hpp b/src/openrct2/actions/WallPlaceAction.hpp index c2d31e7d52..5be0adff99 100644 --- a/src/openrct2/actions/WallPlaceAction.hpp +++ b/src/openrct2/actions/WallPlaceAction.hpp @@ -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 diff --git a/src/openrct2/rct1/RCT1.h b/src/openrct2/rct1/RCT1.h index 03febc080e..a416dead03 100644 --- a/src/openrct2/rct1/RCT1.h +++ b/src/openrct2/rct1/RCT1.h @@ -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 diff --git a/src/openrct2/rct1/S4Importer.cpp b/src/openrct2/rct1/S4Importer.cpp index 8b44947b7f..7513170d3c 100644 --- a/src/openrct2/rct1/S4Importer.cpp +++ b/src/openrct2/rct1/S4Importer.cpp @@ -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 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; } diff --git a/src/openrct2/rct1/Tables.cpp b/src/openrct2/rct1/Tables.cpp index 242630c663..20a1a9e623 100644 --- a/src/openrct2/rct1/Tables.cpp +++ b/src/openrct2/rct1/Tables.cpp @@ -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) diff --git a/src/openrct2/rct12/RCT12.cpp b/src/openrct2/rct12/RCT12.cpp index 7572df492d..4fa9583642 100644 --- a/src/openrct2/rct12/RCT12.cpp +++ b/src/openrct2/rct12/RCT12.cpp @@ -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 diff --git a/src/openrct2/world/TileElement.h b/src/openrct2/world/TileElement.h index f772d9d8e6..3453f7323b 100644 --- a/src/openrct2/world/TileElement.h +++ b/src/openrct2/world/TileElement.h @@ -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); diff --git a/src/openrct2/world/Wall.cpp b/src/openrct2/world/Wall.cpp index ec5b5eb2db..e742051d8a 100644 --- a/src/openrct2/world/Wall.cpp +++ b/src/openrct2/world/Wall.cpp @@ -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; } diff --git a/src/openrct2/world/Wall.h b/src/openrct2/world/Wall.h index 5ed51fb252..bde25e1ad5 100644 --- a/src/openrct2/world/Wall.h +++ b/src/openrct2/world/Wall.h @@ -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);