1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2026-01-15 11:03:00 +01:00

Add isHidden field to plug-in TileElements

With this field, plug-in creators are encouraged to use `isHidden` rather than spawning corrupt elements to hide other tile elements, and their scripts won't need updating when `isHidden` becomes a real field that does not alter anything other than the element itself.
This commit is contained in:
Hielke Morsink
2020-05-05 00:05:55 +02:00
parent e5b1508694
commit f88951eb33
2 changed files with 89 additions and 3 deletions

View File

@@ -356,12 +356,15 @@ declare global {
}
type TileElementType =
"surface" | "footpath" | "track" | "small_scenery" | "wall" | "entrance" | "large_scenery" | "banner" | "openrct2_corrupt_deprecated";
"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
{
@@ -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_deprecated")
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 = 255 guarantee this
TileElement* insertedElement = tile_element_insert({ _coords, 0xFF }, 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(