1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2026-01-23 23:04:36 +01:00

Merge pull request #11601 from Broxzier/bugfix/corrupt-elem-type-typescript

Add missing "openrct2_corrupt" element type
This commit is contained in:
Michael Steenbeek
2020-05-05 18:53:08 +02:00
committed by GitHub
4 changed files with 94 additions and 5 deletions

View File

@@ -356,12 +356,15 @@ declare global {
}
type TileElementType =
"surface" | "footpath" | "track" | "small_scenery" | "wall" | "entrance" | "large_scenery" | "banner";
"surface" | "footpath" | "track" | "small_scenery" | "wall" | "entrance" | "large_scenery" | "banner"
/** This only exist to retrieve the types for existing corrupt elements. For hiding elements, use the isHidden field instead. */
| "openrct2_corrupt_deprecated";
interface BaseTileElement {
type: TileElementType;
baseHeight: number;
clearanceHeight: number;
isHidden: boolean; /** Take caution when changing this field, it may invalidate TileElements you have stored in your script. */
}
interface SurfaceElement extends BaseTileElement {

View File

@@ -13,6 +13,7 @@
# include "../Context.h"
# include "../common.h"
# include "../core/Guard.hpp"
# include "../world/Footpath.h"
# include "../world/Scenery.h"
# include "../world/Sprite.h"
@@ -22,6 +23,7 @@
# include <cstdio>
# include <cstring>
# include <utility>
namespace OpenRCT2::Scripting
{
@@ -62,7 +64,7 @@ namespace OpenRCT2::Scripting
case TILE_ELEMENT_TYPE_BANNER:
return "banner";
case TILE_ELEMENT_TYPE_CORRUPT:
return "openrct2_corrupt";
return "openrct2_corrupt_deprecated";
default:
return "unknown";
}
@@ -87,10 +89,14 @@ namespace OpenRCT2::Scripting
type = TILE_ELEMENT_TYPE_LARGE_SCENERY;
else if (value == "banner")
type = TILE_ELEMENT_TYPE_BANNER;
else if (value == "openrct2_corrupt")
type = TILE_ELEMENT_TYPE_CORRUPT;
else
{
if (value == "openrct2_corrupt_deprecated")
std::puts(
"Creation of new corrupt elements is deprecated. To hide elements, use the 'hidden' property instead.");
return;
}
_element->type = type;
map_invalidate_tile_full(_coords);
}
@@ -491,6 +497,82 @@ namespace OpenRCT2::Scripting
}
}
bool isHidden_get() const
{
// TODO: Simply return the 'hidden' field once corrupt elements are superseded.
const TileElement* element = map_get_first_element_at(_coords);
bool previousElementWasUsefulCorrupt = false;
do
{
if (element == _element)
return previousElementWasUsefulCorrupt;
if (element->GetType() == TILE_ELEMENT_TYPE_CORRUPT)
previousElementWasUsefulCorrupt = !previousElementWasUsefulCorrupt;
else
previousElementWasUsefulCorrupt = false;
} while (!(element++)->IsLastForTile());
Guard::Assert(false);
return false;
}
void isHidden_set(bool hide)
{
// TODO: Simply update the 'hidden' field once corrupt elements are superseded.
ThrowIfGameStateNotMutable();
const bool isHidden = isHidden_get();
if (hide == isHidden)
return;
if (hide)
{
// Get index of our current element (has to be done now before inserting the corrupt element)
const auto elementIndex = _element - map_get_first_element_at(_coords);
// Insert corrupt element at the end of the list for this tile
// Note: Z = MAX_ELEMENT_HEIGHT to guarantee this
TileElement* insertedElement = tile_element_insert({ _coords, MAX_ELEMENT_HEIGHT }, 0);
if (insertedElement == nullptr)
{
// TODO: Show error
return;
}
insertedElement->SetType(TILE_ELEMENT_TYPE_CORRUPT);
// Since inserting a new element may move the tile elements in memory, we have to update the local pointer
_element = map_get_first_element_at(_coords) + elementIndex;
// Move the corrupt element down in the list until it's right under our element
while (insertedElement > _element)
{
std::swap<TileElement>(*insertedElement, *(insertedElement - 1));
insertedElement--;
// Un-swap the last-for-tile flag
if (insertedElement->IsLastForTile())
{
insertedElement->SetLastForTile(false);
(insertedElement + 1)->SetLastForTile(true);
}
}
// Now the corrupt element took the hidden element's place, increment it by one
_element++;
// Update base and clearance heights of inserted corrupt element to match the element to hide
insertedElement->base_height = insertedElement->clearance_height = _element->base_height;
}
else
{
TileElement* const elementToRemove = _element - 1;
Guard::Assert(elementToRemove->GetType() == TILE_ELEMENT_TYPE_CORRUPT);
tile_element_remove(elementToRemove);
_element--;
}
map_invalidate_tile_full(_coords);
}
uint8_t age_get() const
{
auto el = _element->AsSmallScenery();
@@ -830,6 +912,7 @@ namespace OpenRCT2::Scripting
// Some
dukglue_register_property(ctx, &ScTileElement::object_get, &ScTileElement::object_set, "object");
dukglue_register_property(ctx, &ScTileElement::isHidden_get, &ScTileElement::isHidden_set, "isHidden");
// Small Scenery | Large Scenery
dukglue_register_property(

View File

@@ -21,6 +21,8 @@ struct rct_scenery_entry;
struct rct_footpath_entry;
using track_type_t = uint16_t;
constexpr const uint8_t MAX_ELEMENT_HEIGHT = 255;
#pragma pack(push, 1)
enum

View File

@@ -421,7 +421,8 @@ GameActionResult::Ptr tile_inspector_any_base_height_offset(
int16_t newBaseHeight = static_cast<int16_t>(tileElement->base_height + heightOffset);
int16_t newClearanceHeight = static_cast<int16_t>(tileElement->clearance_height + heightOffset);
if (newBaseHeight < 0 || newBaseHeight > 0xff || newClearanceHeight < 0 || newClearanceHeight > 0xff)
if (newBaseHeight < 0 || newBaseHeight > MAX_ELEMENT_HEIGHT || newClearanceHeight < 0
|| newClearanceHeight > MAX_ELEMENT_HEIGHT)
{
return std::make_unique<GameActionResult>(GA_ERROR::UNKNOWN, STR_NONE);
}