From ab5bfffde0e406b4b1bce0121bab5c3a40488933 Mon Sep 17 00:00:00 2001 From: Ted John Date: Tue, 11 Feb 2020 23:25:19 +0000 Subject: [PATCH] Fix tile element scripting --- distribution/openrct2.d.ts | 30 +- src/openrct2/scripting/ScMap.hpp | 5 +- src/openrct2/scripting/ScTile.hpp | 517 +++--------------------------- 3 files changed, 56 insertions(+), 496 deletions(-) diff --git a/distribution/openrct2.d.ts b/distribution/openrct2.d.ts index ffa0bc929e..ccc7ba579c 100644 --- a/distribution/openrct2.d.ts +++ b/distribution/openrct2.d.ts @@ -159,20 +159,22 @@ export interface BaseTileElement { broken: boolean; } -export interface TileElement extends BaseTileElement { - /** - * Gets the element as a specific type to access its properties - */ - asSurface(): SurfaceElement | null; - asFootpath(): FootpathElement | null; - asTrack(): TrackElement | null; - asSmallScenery(): SmallSceneryElement | null; - asEntrance(): EntranceElement | null; - asWall(): WallElement | null; - asLargeScenery(): LargeSceneryElement | null; - asBanner(): BannerElement | null; - asCorruptElement(): CorruptElement | null; -} +// export interface TileElement extends BaseTileElement { +// /** +// * Gets the element as a specific type to access its properties +// */ +// asSurface(): SurfaceElement | null; +// asFootpath(): FootpathElement | null; +// asTrack(): TrackElement | null; +// asSmallScenery(): SmallSceneryElement | null; +// asEntrance(): EntranceElement | null; +// asWall(): WallElement | null; +// asLargeScenery(): LargeSceneryElement | null; +// asBanner(): BannerElement | null; +// asCorruptElement(): CorruptElement | null; +// } + +export type TileElement = SurfaceElement | FootpathElement | TrackElement; export interface SurfaceElement extends BaseTileElement { slope: number; diff --git a/src/openrct2/scripting/ScMap.hpp b/src/openrct2/scripting/ScMap.hpp index 5ffea1e1e4..61f12c2c94 100644 --- a/src/openrct2/scripting/ScMap.hpp +++ b/src/openrct2/scripting/ScMap.hpp @@ -52,8 +52,9 @@ namespace OpenRCT2::Scripting std::shared_ptr getTile(int32_t x, int32_t y) { - auto firstElement = map_get_first_element_at({ x, y }); - return std::make_shared(firstElement); + auto coords = TileCoordsXY(x, y).ToCoordsXY(); + auto firstElement = map_get_first_element_at(coords); + return std::make_shared(coords, firstElement); } std::shared_ptr getThing(int32_t id) diff --git a/src/openrct2/scripting/ScTile.hpp b/src/openrct2/scripting/ScTile.hpp index 69c605106b..c2603250b9 100644 --- a/src/openrct2/scripting/ScTile.hpp +++ b/src/openrct2/scripting/ScTile.hpp @@ -20,18 +20,23 @@ namespace OpenRCT2::Scripting { + class ScSurfaceElement; + class ScTileElement { protected: + CoordsXY _coords; TileElement* _element; public: - ScTileElement(TileElement* element) - : _element(element) + ScTileElement(CoordsXY coords, TileElement* element) + : _coords(coords) + , _element(element) { } - std::string footpathType_get() const + private: + std::string type_get() const { switch (_element->GetType()) { @@ -58,11 +63,6 @@ namespace OpenRCT2::Scripting } } - template T* getAs() - { - return static_cast(this); - } - bool broken_get() const { return _element->flags & TILE_ELEMENT_FLAG_BROKEN; @@ -97,485 +97,55 @@ namespace OpenRCT2::Scripting _element->clearance_height = newClearanceHeight; } - static void Register(duk_context* ctx); - template static void RegisterSharedProperties(duk_context* ctx); - }; - - class ScSurfaceElement final : public ScTileElement - { - uint8_t slope_get() - { - return _element->AsSurface()->GetSlope(); - } - void slope_set(uint8_t value) - { - // TODO: Give warning when value > TILE_ELEMENT_SURFACE_SLOPE_MASK - _element->AsSurface()->SetSlope(value); - } - - uint8_t terrain_get() - { - return _element->AsSurface()->GetSurfaceStyle(); - } - void terrain_set(uint8_t value) - { - _element->AsSurface()->SetSurfaceStyle(value); - } - - uint8_t waterHeight_get() - { - return _element->AsSurface()->GetWaterHeight(); - } - void waterHeight_set(uint8_t value) - { - // TODO: Give warning when value > TILE_ELEMENT_SURFACE_WATER_HEIGHT_MASK - _element->AsSurface()->SetWaterHeight(value); - } - uint8_t grassLength_get() { - return _element->AsSurface()->GetGrassLength(); + auto el = _element->AsSurface(); + if (el != nullptr) + return el->GetGrassLength(); + return 0; } void grassLength_set(uint8_t value) { - // TODO: Give warning when value > GRASS_LENGTH_CLUMPS_2 - return _element->AsSurface()->SetGrassLength(value); + auto el = _element->AsSurface(); + if (el != nullptr) + { + // TODO: Give warning when value > GRASS_LENGTH_CLUMPS_2 + el->SetGrassLengthAndInvalidate(value, _coords); + } } - uint8_t ownership_get() + bool hasOwnership_get() { - return _element->AsSurface()->GetOwnership(); - } - void ownership_set(uint8_t flags) - { - _element->AsSurface()->SetOwnership(flags); - } - - uint8_t parkFences_get() - { - return _element->AsSurface()->GetParkFences(); - } - void parkFences_set(uint8_t flags) - { - return _element->AsSurface()->SetParkFences(flags); + auto el = _element->AsSurface(); + if (el != nullptr) + return el->GetOwnership() & OWNERSHIP_OWNED; + return false; } public: static void Register(duk_context* ctx) { - RegisterSharedProperties(ctx); - dukglue_register_property(ctx, &slope_get, &slope_set, "slope"); - dukglue_register_property(ctx, &terrain_get, &terrain_set, "terrain"); - dukglue_register_property(ctx, &waterHeight_get, &waterHeight_set, "waterHeight"); - dukglue_register_property(ctx, &grassLength_get, &grassLength_set, "grassLength"); - dukglue_register_property(ctx, &ownership_get, &ownership_set, "ownership"); - dukglue_register_property(ctx, &waterHeight_get, &parkFences_set, "parkFences"); + dukglue_register_property(ctx, &ScTileElement::type_get, nullptr, "type"); + dukglue_register_property(ctx, &ScTileElement::broken_get, &ScTileElement::broken_set, "broken"); + dukglue_register_property(ctx, &ScTileElement::baseHeight_get, &ScTileElement::baseHeight_set, "baseHeight"); + dukglue_register_property( + ctx, &ScTileElement::clearanceHeight_get, &ScTileElement::clearanceHeight_set, "clearanceHeight"); + dukglue_register_property(ctx, &ScTileElement::grassLength_get, &ScTileElement::grassLength_set, "grassLength"); + dukglue_register_property(ctx, &ScTileElement::hasOwnership_get, nullptr, "hasOwnership"); } }; - class ScFootpathElement final : public ScTileElement - { - class ScFootpathAddition - { - class ScFootpathAdditionStatus - { - protected: - TileElement* _element; - - public: - ScFootpathAdditionStatus(TileElement* element) - : _element(element) - { - } - - uint8_t north_get() - { - return _element->AsPath()->GetAdditionStatus() & 3; - } - void north_set(uint8_t value) - { - auto addition = _element->AsPath()->GetAdditionStatus(); - addition &= ~3; - addition |= value & 3; - _element->AsPath()->SetAdditionStatus(addition); - } - - uint8_t east_get() - { - return _element->AsPath()->GetAdditionStatus() & 3; - } - void east_set(uint8_t value) - { - auto addition = _element->AsPath()->GetAdditionStatus(); - addition &= ~(3 << 2); - addition |= (value & 3) << 2; - _element->AsPath()->SetAdditionStatus(addition); - } - - uint8_t south_get() - { - return _element->AsPath()->GetAdditionStatus() & 3; - } - void south_set(uint8_t value) - { - auto addition = _element->AsPath()->GetAdditionStatus(); - addition &= ~(3 << 4); - addition |= (value & 3) << 4; - _element->AsPath()->SetAdditionStatus(addition); - } - - uint8_t west_get() - { - return _element->AsPath()->GetAdditionStatus() & 3; - } - void west_set(uint8_t value) - { - auto addition = _element->AsPath()->GetAdditionStatus(); - addition &= ~(3 << 6); - addition |= (value & 3) << 6; - _element->AsPath()->SetAdditionStatus(addition); - } - - static void Register(duk_context* ctx) - { - dukglue_register_property(ctx, &north_get, &north_set, "north"); - dukglue_register_property(ctx, &east_get, &east_set, "east"); - dukglue_register_property(ctx, &south_get, &south_set, "south"); - dukglue_register_property(ctx, &west_get, &west_set, "west"); - } - }; - - protected: - TileElement* _element; - bool VerifyPathAdditionExists() - { - if (!_element->AsPath()->HasAddition()) - { - // TODO: Show warning in console that the path addition has been removed - return false; - } - return true; - } - - public: - ScFootpathAddition(TileElement* element) - : _element(element) - { - } - - void Remove() - { - _element->AsPath()->SetAddition(0); - } - - uint8_t type_get() - { - if (!VerifyPathAdditionExists()) - return 0; - return _element->AsPath()->GetAddition(); - } - void type_set(uint8_t value) - { - _element->AsPath()->SetAddition(value); - } - - bool isBin_get() - { - if (!VerifyPathAdditionExists()) - return false; - - auto sceneryEntry = _element->AsPath()->GetAdditionEntry(); - return sceneryEntry->path_bit.flags & PATH_BIT_FLAG_IS_BIN; - } - bool isBench_get() - { - if (!VerifyPathAdditionExists()) - return false; - - auto sceneryEntry = _element->AsPath()->GetAdditionEntry(); - return sceneryEntry->path_bit.flags & PATH_BIT_FLAG_IS_BENCH; - } - bool isLamp_get() - { - if (!VerifyPathAdditionExists()) - return false; - - auto sceneryEntry = _element->AsPath()->GetAdditionEntry(); - return sceneryEntry->path_bit.flags & PATH_BIT_FLAG_LAMP; - } - bool isBreakable_get() - { - if (!VerifyPathAdditionExists()) - return false; - - auto sceneryEntry = _element->AsPath()->GetAdditionEntry(); - return sceneryEntry->path_bit.flags & PATH_BIT_FLAG_BREAKABLE; - } - bool isJumpingFountainWater_get() - { - if (!VerifyPathAdditionExists()) - return false; - - auto sceneryEntry = _element->AsPath()->GetAdditionEntry(); - return sceneryEntry->path_bit.flags & PATH_BIT_FLAG_JUMPING_FOUNTAIN_WATER; - } - bool isJumpingFountainSnow_get() - { - if (!VerifyPathAdditionExists()) - return false; - - auto sceneryEntry = _element->AsPath()->GetAdditionEntry(); - return sceneryEntry->path_bit.flags & PATH_BIT_FLAG_JUMPING_FOUNTAIN_SNOW; - } - bool allowedOnQueue_get() - { - if (!VerifyPathAdditionExists()) - return false; - - auto sceneryEntry = _element->AsPath()->GetAdditionEntry(); - return sceneryEntry->path_bit.flags & PATH_BIT_FLAG_DONT_ALLOW_ON_QUEUE; - } - bool allowedOnSlope_get() - { - if (!VerifyPathAdditionExists()) - return false; - - auto sceneryEntry = _element->AsPath()->GetAdditionEntry(); - return sceneryEntry->path_bit.flags & PATH_BIT_FLAG_DONT_ALLOW_ON_SLOPE; - } - bool isQueueScreen_get() - { - if (!VerifyPathAdditionExists()) - return false; - - auto sceneryEntry = _element->AsPath()->GetAdditionEntry(); - return sceneryEntry->path_bit.flags & PATH_BIT_FLAG_IS_QUEUE_SCREEN; - } - - std::shared_ptr status_get() - { - return std::make_shared(_element); - } - - static void Register(duk_context* ctx) - { - // Addition status properties (.status.north, .status.east, etc.) - ScFootpathAdditionStatus::Register(ctx); - - // Functions - dukglue_register_method(ctx, &ScFootpathAddition::Remove, "remove"); - - // Properties - dukglue_register_property(ctx, &type_get, &type_set, "type"); - dukglue_register_property(ctx, &isBin_get, nullptr, "isBin"); - dukglue_register_property(ctx, &isBench_get, nullptr, "isBench"); - dukglue_register_property(ctx, &isLamp_get, nullptr, "isLamp"); - dukglue_register_property(ctx, &isBreakable_get, nullptr, "isBreakable"); - dukglue_register_property(ctx, &isJumpingFountainWater_get, nullptr, "isJumpingFountainWater"); - dukglue_register_property(ctx, &isJumpingFountainSnow_get, nullptr, "isJumpingFountainSnow"); - dukglue_register_property(ctx, &allowedOnQueue_get, nullptr, "allowedOnQueue"); - dukglue_register_property(ctx, &allowedOnSlope_get, nullptr, "allowedOnSlope"); - dukglue_register_property(ctx, &isQueueScreen_get, nullptr, "isQueueScreen"); - dukglue_register_property(ctx, &status_get, nullptr, "status"); - } - }; - - uint8_t footpathType_get() - { - return _element->AsPath()->GetPathEntryIndex(); - } - void type_set(uint8_t index) - { - auto entry = get_path_surface_entry(index); - if (entry == nullptr) - { - // TODO: Give warning (most likely only happens when index > MAX_PATH_OBJECTS) - return; - } - _element->AsPath()->SetPathEntryIndex(index); - } - - bool isSloped_get() - { - return _element->AsPath()->IsSloped(); - } - void isSlope_set(bool value) - { - _element->AsPath()->SetSloped(value); - } - - bool isQueue_get() - { - return _element->AsPath()->IsQueue(); - } - - std::shared_ptr addition_get() - { - if (!_element->AsPath()->HasAddition()) - return nullptr; - - return std::make_shared(_element); - } - - uint8_t edges_get() - { - return _element->AsPath()->GetEdges(); - } - void edges_set(uint8_t value) - { - _element->AsPath()->SetEdges(value); - } - - uint8_t corners_get() - { - return _element->AsPath()->GetCorners(); - } - void corners_set(uint8_t value) - { - _element->AsPath()->SetCorners(value); - } - - uint8_t rideIndex_get() - { - if (!_element->AsPath()->IsQueue()) - { - // TODO: Show warning that "path is not a queue" - } - return _element->AsPath()->GetRideIndex(); - } - - public: - static void Register(duk_context* ctx) - { - // Register shared properties (baseheight, clearance height, etc.) - RegisterSharedProperties(ctx); - - // Register path addition properties (.addition.isBench, .addition.isLamp, etc.) - ScFootpathAddition::Register(ctx); - - // Specific properties - dukglue_register_property(ctx, &footpathType_get, &type_set, "footpathType"); - dukglue_register_property(ctx, &isSloped_get, &isSlope_set, "isSloped"); - dukglue_register_property(ctx, &isQueue_get, nullptr, "isQueue"); - dukglue_register_property(ctx, &addition_get, nullptr, "addition"); - dukglue_register_property(ctx, &edges_get, &edges_set, "edges"); - dukglue_register_property(ctx, &corners_get, &corners_set, "corners"); - dukglue_register_property(ctx, &rideIndex_get, nullptr, "rideIndex"); - } - }; - - class ScTrackElement final : public ScTileElement - { - auto track_ride_index_get() const - { - return _element->AsTrack()->GetRideIndex(); - } - - public: - static void Register(duk_context* ctx) - { - RegisterSharedProperties(ctx); - dukglue_register_property(ctx, &ScTrackElement::track_ride_index_get, nullptr, "rideIndex"); - } - }; - - class ScSmallSceneryElement final : public ScTileElement - { - public: - static void Register(duk_context* ctx) - { - RegisterSharedProperties(ctx); - } - }; - - class ScEntranceElement final : public ScTileElement - { - public: - static void Register(duk_context* ctx) - { - RegisterSharedProperties(ctx); - } - }; - - class ScWallElement final : public ScTileElement - { - public: - static void Register(duk_context* ctx) - { - RegisterSharedProperties(ctx); - } - }; - - class ScLargeSceneryElement final : public ScTileElement - { - public: - static void Register(duk_context* ctx) - { - RegisterSharedProperties(ctx); - } - }; - - class ScBannerElement final : public ScTileElement - { - public: - static void Register(duk_context* ctx) - { - RegisterSharedProperties(ctx); - } - }; - - void ScTileElement::Register(duk_context* ctx) - { - dukglue_register_method(ctx, &ScTileElement::getAs, "asSurface"); - dukglue_register_method(ctx, &ScTileElement::getAs, "asFootpath"); - dukglue_register_method(ctx, &ScTileElement::getAs, "asTrack"); - dukglue_register_method(ctx, &ScTileElement::getAs, "asSmallScenery"); - dukglue_register_method(ctx, &ScTileElement::getAs, "asEntrance"); - dukglue_register_method(ctx, &ScTileElement::getAs, "asWall"); - dukglue_register_method(ctx, &ScTileElement::getAs, "asLargeScenery"); - dukglue_register_method(ctx, &ScTileElement::getAs, "asBanner"); - - // Shared properties - RegisterSharedProperties(ctx); - - // Register type specific properties - ScSurfaceElement ::Register(ctx); - ScFootpathElement::Register(ctx); - ScTrackElement ::Register(ctx); - ScSmallSceneryElement ::Register(ctx); - ScEntranceElement ::Register(ctx); - ScWallElement ::Register(ctx); - ScLargeSceneryElement ::Register(ctx); - ScBannerElement ::Register(ctx); - } - - template void ScTileElement::RegisterSharedProperties(duk_context* ctx) - { - // When you register a member function of a parent class, it belongs to the parent and cannot be accessed by its - // children. To get around this issue, we need to force the function pointer types to be of the class we want them to be - // available for. This needs to be done for every child. - dukglue_register_property( - ctx, static_cast(&ScTileElement::footpathType_get), nullptr, "type"); - dukglue_register_property( - ctx, static_cast(&ScTileElement::broken_get), - static_cast(&ScTileElement::broken_set), "broken"); - dukglue_register_property( - ctx, static_cast(&ScTileElement::baseHeight_get), - static_cast(&ScTileElement::baseHeight_set), "baseHeight"); - dukglue_register_property( - ctx, static_cast(&ScTileElement::clearanceHeight_get), - static_cast(&ScTileElement::clearanceHeight_set), "clearanceHeight"); - } - class ScTile { private: + CoordsXY _coords; TileElement* _first; size_t _count = 0; public: - ScTile(TileElement* first) - : _first(first) + ScTile(CoordsXY coords, TileElement* first) + : _coords(coords) + , _first(first) { _count = 0; if (first != nullptr) @@ -588,7 +158,7 @@ namespace OpenRCT2::Scripting } } - size_t numElements_get() + size_t elements_get() { return _count; } @@ -597,25 +167,12 @@ namespace OpenRCT2::Scripting { if (index >= _count) return nullptr; - return std::make_shared(&_first[index]); + return std::make_shared(_coords, &_first[index]); } - // This is not a good idea as the array is generated each time elements is accessed and - // chances are scripts will do tile.elements[0], tile.elements[1]... - // std::vector> elements_get() - // { - // std::vector> elements; - // for (size_t i = 0; i < _count; i++) - // { - // elements.push_back(std::make_shared(&_first[i])); - // } - // return elements; - // } - static void Register(duk_context* ctx) { - // dukglue_register_property(ctx, &ScTile::elements_get, nullptr, "elements"); - dukglue_register_property(ctx, &ScTile::numElements_get, nullptr, "numElements"); + dukglue_register_property(ctx, &ScTile::elements_get, nullptr, "elements"); dukglue_register_method(ctx, &ScTile::getElement, "getElement"); } };