diff --git a/distribution/changelog.txt b/distribution/changelog.txt index a594bc98e1..9b7a2cd070 100644 --- a/distribution/changelog.txt +++ b/distribution/changelog.txt @@ -5,6 +5,7 @@ - Feature: [#21521] [Plugin] Add hook 'park.guest.softcap.calculate' called before calculating the soft guest cap. - Feature: [#22694] Park graphs have tooltips and can be resized like finance graphs. - Feature: [#22758] The table of ‘real’ peep names can now be changed using Peep Names objects. +- Feature: [#22842] [Plugin] Expose large scenery object tiles to the plugin API. - Improved: [#22470] Android: automatically detect RCT2 installs in /sdcard/rct2. - Improved: [#22735] The map generator has a redesigned interface that is much more user friendly. - Improved: [#22777] Add long flat-to-steep track pieces to the Wooden and Classic Wooden Roller Coasters. diff --git a/distribution/openrct2.d.ts b/distribution/openrct2.d.ts index 1011d849a0..507fd782f4 100644 --- a/distribution/openrct2.d.ts +++ b/distribution/openrct2.d.ts @@ -1950,6 +1950,39 @@ declare global { interface LargeSceneryObject extends SceneryObject { + readonly tiles: LargeSceneryObjectTile[]; + } + + interface LargeSceneryObjectTile { + /** + * The offset from tile index 0's location to this tile + */ + readonly offset: CoordsXYZ; + + /** + * The clearance height for this tile + */ + readonly zClearance: number; + + /** + * Set if the tile will draw supports + */ + readonly hasSupports: boolean; + + /** + * Set if the tile allows for drawing supports above this tile + */ + readonly allowSupportsAbove: boolean; + + /** + * A tile can be split into 4 sub tiles this defines what of those 4 are occupied by this tile + */ + readonly corners: number; + + /** + * Indicates if an edge can have walls built on it + */ + readonly walls: number; } interface WallObject extends SceneryObject { @@ -2658,7 +2691,7 @@ declare global { "waiting_to_depart" | "waiting_to_start"; - type CrashParticleType = "corner" | "rod" | "wheel" | "panel" | "seat"; + type CrashParticleType = "corner" | "rod" | "wheel" | "panel" | "seat"; /** * Override properties for launch data. All properties except colour are randomly @@ -4472,28 +4505,28 @@ declare global { ButtonWidget | CheckboxWidget | ColourPickerWidget | CustomWidget | DropdownWidget | GroupBoxWidget | LabelWidget | ListViewWidget | SpinnerWidget | TextBoxWidget | ViewportWidget; - type IconName = + type IconName = "arrow_down" | "arrow_up" | "award" | "awards" | "chain_lift" | "chat" | "cheats" | "closed" | "construction" | "copy" | "demolish" | "empty" | "eyedropper" | "fast_forward" | "finance" | "floppy_disk" | "game_speed_indicator" | - "game_speed_indicator_double" | "glassy_recolourable" | "graph" | "guest_inventory" | "guests" | - "hearing" | "hide_full" | "hide_partial" | "hide_scenery" | "hide_supports" | "hide_vegetation" | "hide_vehicles" | - "kiosks_and_facilities" | "large_scenery" | "legacy_paths" | "link_chain" | "locate" | "logo" | "logo_text" | "map" | - "map_east" | "map_east_pressed" | "map_gen_land" | "map_gen_noise" | "map_gen_trees" | "map_north" | "map_north_pressed" | - "map_south" | "map_south_pressed" | "map_west" | "map_west_pressed" | "mechanic" | "mirror_arrow" | - "mountain_tool_even" | "mountain_tool_odd" | "multiplayer" | "multiplayer_desync" | "multiplayer_sync" | - "multiplayer_toolbar" | "multiplayer_toolbar_pressed" | "music" | "mute" | "mute_pressed" | "news_messages" | + "game_speed_indicator_double" | "glassy_recolourable" | "graph" | "guest_inventory" | "guests" | + "hearing" | "hide_full" | "hide_partial" | "hide_scenery" | "hide_supports" | "hide_vegetation" | "hide_vehicles" | + "kiosks_and_facilities" | "large_scenery" | "legacy_paths" | "link_chain" | "locate" | "logo" | "logo_text" | "map" | + "map_east" | "map_east_pressed" | "map_gen_land" | "map_gen_noise" | "map_gen_trees" | "map_north" | "map_north_pressed" | + "map_south" | "map_south_pressed" | "map_west" | "map_west_pressed" | "mechanic" | "mirror_arrow" | + "mountain_tool_even" | "mountain_tool_odd" | "multiplayer" | "multiplayer_desync" | "multiplayer_sync" | + "multiplayer_toolbar" | "multiplayer_toolbar_pressed" | "music" | "mute" | "mute_pressed" | "news_messages" | "new_ride" | "next" | "no_entry" | "open" | "paintbrush" | "palette_invisible" | "palette_invisible_pressed" | "park" | - "paste" | "path_railings" | "path_surfaces" | "paths" | "patrol" | "pause" | "pickup" | "placeholder" | "previous" | - "question" | "rct1_close_off" | "rct1_close_off_pressed" | "rct1_close_on" | "rct1_close_on_pressed" | "rct1_open_off" | - "rct1_open_off_pressed" | "rct1_open_on" | "rct1_open_on_pressed" | "rct1_simulate_off" | "rct1_simulate_off_pressed" | - "rct1_simulate_on" | "rct1_simulate_on_pressed" | "rct1_test_off" | "rct1_test_off_pressed" | "rct1_test_on" | - "rct1_test_on_pressed" | "reload" | "rename" | "research" | "ride" | "ride_stations" | "rides_gentle" | - "rides_rollercoasters" | "rides_shop" | "rides_thrill" | "rides_transport" | "rides_water" | "rotate_arrow" | "scenery" | - "scenery_cluster" | "scenery_paths" | "scenery_paths_items" | "scenery_scatter_high" | "scenery_scatter_low" | - "scenery_scatter_medium" | "scenery_signage" | "scenery_statues" | "scenery_trees" | "scenery_urban" | "scenery_walls" | - "search" | "selection_edge_ne" | "selection_edge_nw" | "selection_edge_se" | "selection_edge_sw" | "server_password" | - "shops_and_stalls" | "sideways_tab" | "sideways_tab_active" | "simulate" | "small_scenery" | "sort" | "stats" | "testing" | - "terrain_edges" | "title_play" | "title_restart" | "title_skip" | "title_stop" | "unmute" | "unmute_pressed" | "view" | + "paste" | "path_railings" | "path_surfaces" | "paths" | "patrol" | "pause" | "pickup" | "placeholder" | "previous" | + "question" | "rct1_close_off" | "rct1_close_off_pressed" | "rct1_close_on" | "rct1_close_on_pressed" | "rct1_open_off" | + "rct1_open_off_pressed" | "rct1_open_on" | "rct1_open_on_pressed" | "rct1_simulate_off" | "rct1_simulate_off_pressed" | + "rct1_simulate_on" | "rct1_simulate_on_pressed" | "rct1_test_off" | "rct1_test_off_pressed" | "rct1_test_on" | + "rct1_test_on_pressed" | "reload" | "rename" | "research" | "ride" | "ride_stations" | "rides_gentle" | + "rides_rollercoasters" | "rides_shop" | "rides_thrill" | "rides_transport" | "rides_water" | "rotate_arrow" | "scenery" | + "scenery_cluster" | "scenery_paths" | "scenery_paths_items" | "scenery_scatter_high" | "scenery_scatter_low" | + "scenery_scatter_medium" | "scenery_signage" | "scenery_statues" | "scenery_trees" | "scenery_urban" | "scenery_walls" | + "search" | "selection_edge_ne" | "selection_edge_nw" | "selection_edge_se" | "selection_edge_sw" | "server_password" | + "shops_and_stalls" | "sideways_tab" | "sideways_tab_active" | "simulate" | "small_scenery" | "sort" | "stats" | "testing" | + "terrain_edges" | "title_play" | "title_restart" | "title_skip" | "title_stop" | "unmute" | "unmute_pressed" | "view" | "water" | "zoom_in" | "zoom_in_background" | "zoom_out" | "zoom_out_background"; interface WidgetBase { diff --git a/src/openrct2/scripting/ScriptEngine.cpp b/src/openrct2/scripting/ScriptEngine.cpp index ab1beaa3a3..c73223c9a0 100644 --- a/src/openrct2/scripting/ScriptEngine.cpp +++ b/src/openrct2/scripting/ScriptEngine.cpp @@ -417,6 +417,7 @@ void ScriptEngine::Initialise() ScSceneryObject::Register(ctx); ScSmallSceneryObject::Register(ctx); ScLargeSceneryObject::Register(ctx); + ScLargeSceneryObjectTile::Register(ctx); ScWallObject::Register(ctx); ScFootpathAdditionObject::Register(ctx); ScBannerObject::Register(ctx); diff --git a/src/openrct2/scripting/ScriptEngine.h b/src/openrct2/scripting/ScriptEngine.h index 12cc0d24a8..7f800d1d0b 100644 --- a/src/openrct2/scripting/ScriptEngine.h +++ b/src/openrct2/scripting/ScriptEngine.h @@ -46,7 +46,7 @@ namespace OpenRCT2 namespace OpenRCT2::Scripting { - static constexpr int32_t OPENRCT2_PLUGIN_API_VERSION = 99; + static constexpr int32_t OPENRCT2_PLUGIN_API_VERSION = 100; // Versions marking breaking changes. static constexpr int32_t API_VERSION_33_PEEP_DEPRECATION = 33; diff --git a/src/openrct2/scripting/bindings/object/ScObject.hpp b/src/openrct2/scripting/bindings/object/ScObject.hpp index bca553c6a0..59d37a957d 100644 --- a/src/openrct2/scripting/bindings/object/ScObject.hpp +++ b/src/openrct2/scripting/bindings/object/ScObject.hpp @@ -12,6 +12,7 @@ #ifdef ENABLE_SCRIPTING # include "../../../Context.h" +# include "../../../object/LargeSceneryObject.h" # include "../../../object/ObjectManager.h" # include "../../../object/RideObject.h" # include "../../../object/SceneryGroupObject.h" @@ -900,6 +901,62 @@ namespace OpenRCT2::Scripting } }; + class ScLargeSceneryObjectTile + { + private: + LargeSceneryTile _tile{}; + + public: + ScLargeSceneryObjectTile(const LargeSceneryTile& tile) + : _tile(tile) + { + } + + static void Register(duk_context* ctx) + { + dukglue_register_property(ctx, &ScLargeSceneryObjectTile::offset_get, nullptr, "offset"); + dukglue_register_property(ctx, &ScLargeSceneryObjectTile::zClearance_get, nullptr, "zClearance"); + dukglue_register_property(ctx, &ScLargeSceneryObjectTile::hasSupports_get, nullptr, "hasSupports"); + dukglue_register_property(ctx, &ScLargeSceneryObjectTile::allowSupportsAbove_get, nullptr, "allowSupportsAbove"); + dukglue_register_property(ctx, &ScLargeSceneryObjectTile::corners_get, nullptr, "corners"); + dukglue_register_property(ctx, &ScLargeSceneryObjectTile::walls_get, nullptr, "walls"); + } + + private: + DukValue offset_get() const + { + auto ctx = GetContext()->GetScriptEngine().GetContext(); + + auto start = CoordsXYZ(_tile.x_offset, _tile.y_offset, _tile.z_offset); + return ToDuk(ctx, start); + } + + int32_t zClearance_get() const + { + return _tile.z_clearance; + } + + bool hasSupports_get() const + { + return !(_tile.flags & LARGE_SCENERY_TILE_FLAG_NO_SUPPORTS); + } + + bool allowSupportsAbove_get() const + { + return _tile.flags & LARGE_SCENERY_TILE_FLAG_ALLOW_SUPPORTS_ABOVE; + } + + uint8_t corners_get() const + { + return (_tile.flags >> 12) & 0xF; + } + + uint8_t walls_get() const + { + return (_tile.flags >> 8) & 0xF; + } + }; + class ScLargeSceneryObject : public ScSceneryObject { public: @@ -911,6 +968,38 @@ namespace OpenRCT2::Scripting static void Register(duk_context* ctx) { dukglue_set_base_class(ctx); + + dukglue_register_property(ctx, &ScLargeSceneryObject::tiles_get, nullptr, "tiles"); + } + + private: + std::vector> tiles_get() const + { + std::vector> result; + auto entry = GetEntry(); + if (entry != nullptr) + { + for (auto* tile = entry->tiles; tile->x_offset != -1; ++tile) + { + result.push_back(std::make_shared(*tile)); + } + } + return result; + } + + LargeSceneryObject* GetObject() const + { + return static_cast(ScObject::GetObject()); + } + + const LargeSceneryEntry* GetEntry() const + { + auto obj = GetObject(); + if (obj != nullptr) + { + return static_cast(obj->GetLegacyData()); + } + return nullptr; } };