From 2913a0686a18b4136d612f22b65228ef136f1644 Mon Sep 17 00:00:00 2001 From: Stephan Spengler Date: Tue, 26 Mar 2024 12:42:09 +0100 Subject: [PATCH] Add banner properties to plugin API for large scenery, walls and banners --- distribution/changelog.txt | 1 + distribution/openrct2.d.ts | 22 +++- src/openrct2/scripting/ScriptEngine.h | 2 +- .../bindings/world/ScTileElement.cpp | 113 +++++++++++++++++- .../bindings/world/ScTileElement.hpp | 6 + 5 files changed, 137 insertions(+), 7 deletions(-) diff --git a/distribution/changelog.txt b/distribution/changelog.txt index e541bd8b81..880b7a8b8b 100644 --- a/distribution/changelog.txt +++ b/distribution/changelog.txt @@ -1,6 +1,7 @@ 0.4.10 (in development) ------------------------------------------------------------------------ - Feature: [#18171] Add port of the RCT1 Stand-Up Roller Coaster. +- Feature: [#21590] [Plugin] Plugins can now read and write banner properties of tile elements. - Feature: [#21636] Add shortcut key for sorting tile elements. - Feature: [objects#294] Add scenery versions of wooden truss supports. - Feature: [objects#295] Flipped version of wooden post. diff --git a/distribution/openrct2.d.ts b/distribution/openrct2.d.ts index 292151d457..c09138fa6c 100644 --- a/distribution/openrct2.d.ts +++ b/distribution/openrct2.d.ts @@ -1558,10 +1558,14 @@ declare global { direction: Direction; object: number; primaryColour: number; + /** If the element is a banner, this is the text colour. */ secondaryColour: number; tertiaryColour: number; - bannerIndex: number | null; slope: Direction; + /** Writing to bannerIndex is deprecated and may result in uncontrolled behaviour. */ + readonly bannerIndex: number | null; + /** If the element is a banner, this is its text. */ + bannerText: string | null; } interface EntranceElement extends BaseTileElement { @@ -1582,16 +1586,28 @@ declare global { direction: Direction; object: number; primaryColour: number; + /** If the element is a banner, this is the text colour. */ secondaryColour: number; tertiaryColour: number; - bannerIndex: number | null; sequence: number; + /** Writing to bannerIndex is deprecated and may result in uncontrolled behaviour. */ + readonly bannerIndex: number | null; + /** If the element is a banner, this is its text. */ + bannerText: string | null; } interface BannerElement extends BaseTileElement { type: "banner"; + direction: Direction; - bannerIndex: number; + object: number; + primaryColour: number; + /** This is the text colour. */ + secondaryColour: number; + /** Writing to bannerIndex is deprecated and may result in uncontrolled behaviour. */ + readonly bannerIndex: number; + bannerText: string; + isNoEntry: boolean; } /** diff --git a/src/openrct2/scripting/ScriptEngine.h b/src/openrct2/scripting/ScriptEngine.h index ba37b88962..dcc7019303 100644 --- a/src/openrct2/scripting/ScriptEngine.h +++ b/src/openrct2/scripting/ScriptEngine.h @@ -47,7 +47,7 @@ namespace OpenRCT2 namespace OpenRCT2::Scripting { - static constexpr int32_t OPENRCT2_PLUGIN_API_VERSION = 83; + static constexpr int32_t OPENRCT2_PLUGIN_API_VERSION = 84; // Versions marking breaking changes. static constexpr int32_t API_VERSION_33_PEEP_DEPRECATION = 33; diff --git a/src/openrct2/scripting/bindings/world/ScTileElement.cpp b/src/openrct2/scripting/bindings/world/ScTileElement.cpp index 53c5111eef..2d90305dbf 100644 --- a/src/openrct2/scripting/bindings/world/ScTileElement.cpp +++ b/src/openrct2/scripting/bindings/world/ScTileElement.cpp @@ -1153,6 +1153,12 @@ namespace OpenRCT2::Scripting duk_push_int(ctx, el->GetEntranceType()); break; } + case TileElementType::Banner: + { + auto* el = _element->AsBanner(); + duk_push_int(ctx, el->GetBanner()->type); + break; + } default: { duk_push_null(ctx); @@ -1207,6 +1213,13 @@ namespace OpenRCT2::Scripting Invalidate(); break; } + case TileElementType::Banner: + { + auto* el = _element->AsBanner(); + el->GetBanner()->type = index; + Invalidate(); + break; + } default: break; } @@ -1314,6 +1327,12 @@ namespace OpenRCT2::Scripting duk_push_int(ctx, el->GetPrimaryColour()); break; } + case TileElementType::Banner: + { + auto* el = _element->AsBanner(); + duk_push_int(ctx, el->GetBanner()->colour); + break; + } default: { duk_push_null(ctx); @@ -1348,6 +1367,13 @@ namespace OpenRCT2::Scripting Invalidate(); break; } + case TileElementType::Banner: + { + auto* el = _element->AsBanner(); + el->GetBanner()->colour = value; + Invalidate(); + break; + } default: break; } @@ -1377,6 +1403,12 @@ namespace OpenRCT2::Scripting duk_push_int(ctx, el->GetSecondaryColour()); break; } + case TileElementType::Banner: + { + auto* el = _element->AsBanner(); + duk_push_int(ctx, el->GetBanner()->text_colour); + break; + } default: { duk_push_null(ctx); @@ -1411,6 +1443,13 @@ namespace OpenRCT2::Scripting Invalidate(); break; } + case TileElementType::Banner: + { + auto* el = _element->AsBanner(); + el->GetBanner()->text_colour = value; + Invalidate(); + break; + } default: break; } @@ -2040,13 +2079,75 @@ namespace OpenRCT2::Scripting duk_push_uint(ctx, _element->GetOwner()); return DukValue::take_from_stack(ctx); } - void ScTileElement::owner_set(uint8_t value) { ThrowIfGameStateNotMutable(); _element->SetOwner(value); } + DukValue ScTileElement::bannerText_get() const + { + auto& scriptEngine = GetContext()->GetScriptEngine(); + auto* ctx = scriptEngine.GetContext(); + BannerIndex idx = _element->GetBannerIndex(); + if (idx == BannerIndex::GetNull()) + duk_push_null(ctx); + else + duk_push_string(ctx, GetBanner(idx)->GetText().c_str()); + return DukValue::take_from_stack(ctx); + } + void ScTileElement::bannerText_set(std::string value) + { + ThrowIfGameStateNotMutable(); + BannerIndex idx = _element->GetBannerIndex(); + if (idx != BannerIndex::GetNull()) + { + auto banner = GetBanner(idx); + banner->text = value; + if (_element->GetType() != TileElementType::Banner) + { + if (value.empty()) + banner->ride_index = BannerGetClosestRideIndex({ banner->position.ToCoordsXY(), 16 }); + else + banner->ride_index = RideId::GetNull(); + + if (banner->ride_index.IsNull()) + banner->flags &= ~BANNER_FLAG_LINKED_TO_RIDE; + else + banner->flags |= BANNER_FLAG_LINKED_TO_RIDE; + } + } + } + + DukValue ScTileElement::isNoEntry_get() const + { + auto& scriptEngine = GetContext()->GetScriptEngine(); + auto* ctx = scriptEngine.GetContext(); + auto* el = _element->AsBanner(); + if (el != nullptr) + duk_push_boolean(ctx, (el->GetBanner()->flags & BANNER_FLAG_NO_ENTRY) != 0); + else + duk_push_null(ctx); + return DukValue::take_from_stack(ctx); + } + void ScTileElement::isNoEntry_set(bool value) + { + ThrowIfGameStateNotMutable(); + auto* el = _element->AsBanner(); + if (el != nullptr) + { + if (value) + { + el->GetBanner()->flags |= BANNER_FLAG_NO_ENTRY; + } + else + { + el->GetBanner()->flags &= ~BANNER_FLAG_NO_ENTRY; + } + Invalidate(); + } + } + void ScTileElement::Invalidate() { MapInvalidateTileFull(_coords); @@ -2070,17 +2171,20 @@ namespace OpenRCT2::Scripting // Track | Small Scenery | Wall | Entrance | Large Scenery | Banner dukglue_register_property(ctx, &ScTileElement::direction_get, &ScTileElement::direction_set, "direction"); - // Path | Small Scenery | Wall | Entrance | Large Scenery + // Path | Small Scenery | Wall | Entrance | Large Scenery | Banner dukglue_register_property(ctx, &ScTileElement::object_get, &ScTileElement::object_set, "object"); - // Small Scenery | Wall | Large Scenery + // Small Scenery | Wall | Large Scenery | Banner dukglue_register_property(ctx, &ScTileElement::primaryColour_get, &ScTileElement::primaryColour_set, "primaryColour"); dukglue_register_property( ctx, &ScTileElement::secondaryColour_get, &ScTileElement::secondaryColour_set, "secondaryColour"); + + // Small Scenery | Wall | Large Scenery dukglue_register_property( ctx, &ScTileElement::tertiaryColour_get, &ScTileElement::tertiaryColour_set, "tertiaryColour"); // Wall | Large Scenery | Banner + dukglue_register_property(ctx, &ScTileElement::bannerText_get, &ScTileElement::bannerText_set, "bannerText"); dukglue_register_property(ctx, &ScTileElement::bannerIndex_get, &ScTileElement::bannerIndex_set, "bannerIndex"); // Path | Track | Entrance @@ -2152,6 +2256,9 @@ namespace OpenRCT2::Scripting ctx, &ScTileElement::footpathObject_get, &ScTileElement::footpathObject_set, "footpathObject"); dukglue_register_property( ctx, &ScTileElement::footpathSurfaceObject_get, &ScTileElement::footpathSurfaceObject_set, "footpathSurfaceObject"); + + // Banner only + dukglue_register_property(ctx, &ScTileElement::isNoEntry_get, &ScTileElement::isNoEntry_set, "isNoEntry"); } } // namespace OpenRCT2::Scripting diff --git a/src/openrct2/scripting/bindings/world/ScTileElement.hpp b/src/openrct2/scripting/bindings/world/ScTileElement.hpp index 4c0ad05c03..31499a24d4 100644 --- a/src/openrct2/scripting/bindings/world/ScTileElement.hpp +++ b/src/openrct2/scripting/bindings/world/ScTileElement.hpp @@ -205,6 +205,12 @@ namespace OpenRCT2::Scripting DukValue owner_get() const; void owner_set(uint8_t value); + DukValue bannerText_get() const; + void bannerText_set(std::string value); + + DukValue isNoEntry_get() const; + void isNoEntry_set(bool value); + void Invalidate(); public: