From 9f95b006d3587db81b6003f92b30ba7de799aafd Mon Sep 17 00:00:00 2001 From: ZehMatt Date: Tue, 10 Aug 2021 16:21:20 +0300 Subject: [PATCH] Move ScTileElement into its own files --- src/openrct2/libopenrct2.vcxproj | 2 + src/openrct2/scripting/ScriptEngine.cpp | 1 + .../scripting/bindings/world/ScTile.hpp | 1551 +--------------- .../bindings/world/ScTileElement.cpp | 1569 +++++++++++++++++ .../bindings/world/ScTileElement.hpp | 198 +++ 5 files changed, 1771 insertions(+), 1550 deletions(-) create mode 100644 src/openrct2/scripting/bindings/world/ScTileElement.cpp create mode 100644 src/openrct2/scripting/bindings/world/ScTileElement.hpp diff --git a/src/openrct2/libopenrct2.vcxproj b/src/openrct2/libopenrct2.vcxproj index dd3f6892d1..67c5d17b36 100644 --- a/src/openrct2/libopenrct2.vcxproj +++ b/src/openrct2/libopenrct2.vcxproj @@ -414,6 +414,7 @@ + @@ -870,6 +871,7 @@ + diff --git a/src/openrct2/scripting/ScriptEngine.cpp b/src/openrct2/scripting/ScriptEngine.cpp index d4f7bb88a4..e5e132ceb1 100644 --- a/src/openrct2/scripting/ScriptEngine.cpp +++ b/src/openrct2/scripting/ScriptEngine.cpp @@ -48,6 +48,7 @@ # include "bindings/world/ScParkMessage.hpp" # include "bindings/world/ScScenario.hpp" # include "bindings/world/ScTile.hpp" +# include "bindings/world/ScTileElement.hpp" # include # include diff --git a/src/openrct2/scripting/bindings/world/ScTile.hpp b/src/openrct2/scripting/bindings/world/ScTile.hpp index 182b20f9ef..2126d5cc0e 100644 --- a/src/openrct2/scripting/bindings/world/ScTile.hpp +++ b/src/openrct2/scripting/bindings/world/ScTile.hpp @@ -21,6 +21,7 @@ # include "../../../world/Surface.h" # include "../../Duktape.hpp" # include "../../ScriptEngine.h" +# include "ScTileElement.hpp" # include # include @@ -28,1556 +29,6 @@ namespace OpenRCT2::Scripting { - class ScSurfaceElement; - - class ScTileElement - { - protected: - CoordsXY _coords; - TileElement* _element; - - public: - ScTileElement(const CoordsXY& coords, TileElement* element) - : _coords(coords) - , _element(element) - { - } - - private: - std::string type_get() const - { - switch (_element->GetType()) - { - case TILE_ELEMENT_TYPE_SURFACE: - return "surface"; - case TILE_ELEMENT_TYPE_PATH: - return "footpath"; - case TILE_ELEMENT_TYPE_TRACK: - return "track"; - case TILE_ELEMENT_TYPE_SMALL_SCENERY: - return "small_scenery"; - case TILE_ELEMENT_TYPE_ENTRANCE: - return "entrance"; - case TILE_ELEMENT_TYPE_WALL: - return "wall"; - case TILE_ELEMENT_TYPE_LARGE_SCENERY: - return "large_scenery"; - case TILE_ELEMENT_TYPE_BANNER: - return "banner"; - case TILE_ELEMENT_TYPE_CORRUPT: - return "openrct2_corrupt_deprecated"; - default: - return "unknown"; - } - } - - void type_set(std::string value) - { - auto type = _element->type; - if (value == "surface") - type = TILE_ELEMENT_TYPE_SURFACE; - else if (value == "footpath") - type = TILE_ELEMENT_TYPE_PATH; - else if (value == "track") - type = TILE_ELEMENT_TYPE_TRACK; - else if (value == "small_scenery") - type = TILE_ELEMENT_TYPE_SMALL_SCENERY; - else if (value == "entrance") - type = TILE_ELEMENT_TYPE_ENTRANCE; - else if (value == "wall") - type = TILE_ELEMENT_TYPE_WALL; - else if (value == "large_scenery") - type = TILE_ELEMENT_TYPE_LARGE_SCENERY; - else if (value == "banner") - type = TILE_ELEMENT_TYPE_BANNER; - 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; - Invalidate(); - } - - uint8_t baseHeight_get() const - { - return _element->base_height; - } - void baseHeight_set(uint8_t newBaseHeight) - { - ThrowIfGameStateNotMutable(); - _element->base_height = newBaseHeight; - Invalidate(); - } - - uint16_t baseZ_get() const - { - return _element->GetBaseZ(); - } - void baseZ_set(uint16_t value) - { - ThrowIfGameStateNotMutable(); - _element->SetBaseZ(value); - Invalidate(); - } - - uint8_t clearanceHeight_get() const - { - return _element->clearance_height; - } - void clearanceHeight_set(uint8_t newClearanceHeight) - { - ThrowIfGameStateNotMutable(); - _element->clearance_height = newClearanceHeight; - Invalidate(); - } - - uint16_t clearanceZ_get() const - { - return _element->GetClearanceZ(); - } - void clearanceZ_set(uint16_t value) - { - ThrowIfGameStateNotMutable(); - _element->SetClearanceZ(value); - Invalidate(); - } - - DukValue slope_get() const - { - auto ctx = GetContext()->GetScriptEngine().GetContext(); - switch (_element->GetType()) - { - case TILE_ELEMENT_TYPE_SURFACE: - { - auto el = _element->AsSurface(); - duk_push_int(ctx, el->GetSlope()); - break; - } - case TILE_ELEMENT_TYPE_WALL: - { - auto el = _element->AsWall(); - duk_push_int(ctx, el->GetSlope()); - break; - } - default: - { - duk_push_null(ctx); - break; - } - } - return DukValue::take_from_stack(ctx); - } - void slope_set(uint8_t value) - { - ThrowIfGameStateNotMutable(); - switch (_element->GetType()) - { - case TILE_ELEMENT_TYPE_SURFACE: - { - auto el = _element->AsSurface(); - el->SetSlope(value); - Invalidate(); - break; - } - case TILE_ELEMENT_TYPE_WALL: - { - auto el = _element->AsWall(); - el->SetSlope(value); - Invalidate(); - break; - } - } - } - - DukValue waterHeight_get() const - { - auto ctx = GetContext()->GetScriptEngine().GetContext(); - auto el = _element->AsSurface(); - if (el != nullptr) - duk_push_int(ctx, el->GetWaterHeight()); - else - duk_push_null(ctx); - return DukValue::take_from_stack(ctx); - } - void waterHeight_set(int32_t value) - { - ThrowIfGameStateNotMutable(); - auto el = _element->AsSurface(); - if (el != nullptr) - { - el->SetWaterHeight(value); - Invalidate(); - } - } - - DukValue surfaceStyle_get() const - { - auto ctx = GetContext()->GetScriptEngine().GetContext(); - auto el = _element->AsSurface(); - if (el != nullptr) - duk_push_int(ctx, el->GetSurfaceStyle()); - else - duk_push_null(ctx); - return DukValue::take_from_stack(ctx); - } - void surfaceStyle_set(uint32_t value) - { - ThrowIfGameStateNotMutable(); - auto el = _element->AsSurface(); - if (el != nullptr) - { - el->SetSurfaceStyle(value); - Invalidate(); - } - } - - DukValue edgeStyle_get() const - { - auto ctx = GetContext()->GetScriptEngine().GetContext(); - auto el = _element->AsSurface(); - if (el != nullptr) - duk_push_int(ctx, el->GetEdgeStyle()); - else - duk_push_null(ctx); - return DukValue::take_from_stack(ctx); - } - void edgeStyle_set(uint32_t value) - { - ThrowIfGameStateNotMutable(); - auto el = _element->AsSurface(); - if (el != nullptr) - { - el->SetEdgeStyle(value); - Invalidate(); - } - } - - DukValue grassLength_get() const - { - auto ctx = GetContext()->GetScriptEngine().GetContext(); - auto el = _element->AsSurface(); - if (el != nullptr) - duk_push_int(ctx, el->GetGrassLength()); - else - duk_push_null(ctx); - return DukValue::take_from_stack(ctx); - } - void grassLength_set(uint8_t value) - { - ThrowIfGameStateNotMutable(); - auto el = _element->AsSurface(); - if (el != nullptr) - { - // TODO: Give warning when value > GRASS_LENGTH_CLUMPS_2 - el->SetGrassLengthAndInvalidate(value, _coords); - Invalidate(); - } - } - - DukValue hasOwnership_get() const - { - auto ctx = GetContext()->GetScriptEngine().GetContext(); - auto el = _element->AsSurface(); - if (el != nullptr) - duk_push_boolean(ctx, el->GetOwnership() & OWNERSHIP_OWNED); - else - duk_push_null(ctx); - return DukValue::take_from_stack(ctx); - } - - DukValue hasConstructionRights_get() - { - auto ctx = GetContext()->GetScriptEngine().GetContext(); - auto el = _element->AsSurface(); - if (el != nullptr) - { - auto ownership = el->GetOwnership(); - duk_push_boolean(ctx, (ownership & OWNERSHIP_OWNED) || (ownership & OWNERSHIP_CONSTRUCTION_RIGHTS_OWNED)); - } - else - duk_push_null(ctx); - return DukValue::take_from_stack(ctx); - } - - DukValue ownership_get() const - { - auto ctx = GetContext()->GetScriptEngine().GetContext(); - auto el = _element->AsSurface(); - if (el != nullptr) - duk_push_int(ctx, el->GetOwnership()); - else - duk_push_null(ctx); - return DukValue::take_from_stack(ctx); - } - void ownership_set(uint8_t value) - { - ThrowIfGameStateNotMutable(); - auto el = _element->AsSurface(); - if (el != nullptr) - { - el->SetOwnership(value); - Invalidate(); - } - } - - DukValue parkFences_get() const - { - auto ctx = GetContext()->GetScriptEngine().GetContext(); - auto el = _element->AsSurface(); - if (el != nullptr) - duk_push_int(ctx, el->GetParkFences()); - else - duk_push_null(ctx); - return DukValue::take_from_stack(ctx); - } - void parkFences_set(uint8_t value) - { - ThrowIfGameStateNotMutable(); - auto el = _element->AsSurface(); - if (el != nullptr) - { - el->SetParkFences(value); - Invalidate(); - } - } - - DukValue trackType_get() const - { - auto ctx = GetContext()->GetScriptEngine().GetContext(); - auto el = _element->AsTrack(); - if (el != nullptr) - duk_push_int(ctx, el->GetTrackType()); - else - duk_push_null(ctx); - return DukValue::take_from_stack(ctx); - } - void trackType_set(uint8_t value) - { - ThrowIfGameStateNotMutable(); - auto el = _element->AsTrack(); - if (el != nullptr) - { - el->SetTrackType(value); - Invalidate(); - } - } - - DukValue sequence_get() const - { - auto ctx = GetContext()->GetScriptEngine().GetContext(); - switch (_element->GetType()) - { - case TILE_ELEMENT_TYPE_LARGE_SCENERY: - { - auto el = _element->AsLargeScenery(); - duk_push_int(ctx, el->GetSequenceIndex()); - break; - } - case TILE_ELEMENT_TYPE_TRACK: - { - auto el = _element->AsTrack(); - if (get_ride(el->GetRideIndex())->type != RIDE_TYPE_MAZE) - duk_push_int(ctx, el->GetSequenceIndex()); - else - duk_push_null(ctx); - break; - } - case TILE_ELEMENT_TYPE_ENTRANCE: - { - auto el = _element->AsEntrance(); - duk_push_int(ctx, el->GetSequenceIndex()); - break; - } - default: - { - duk_push_null(ctx); - break; - } - } - return DukValue::take_from_stack(ctx); - } - void sequence_set(uint8_t value) - { - ThrowIfGameStateNotMutable(); - switch (_element->GetType()) - { - case TILE_ELEMENT_TYPE_LARGE_SCENERY: - { - auto el = _element->AsLargeScenery(); - el->SetSequenceIndex(value); - Invalidate(); - break; - } - case TILE_ELEMENT_TYPE_TRACK: - { - auto el = _element->AsTrack(); - if (get_ride(el->GetRideIndex())->type != RIDE_TYPE_MAZE) - { - el->SetSequenceIndex(value); - Invalidate(); - } - break; - } - case TILE_ELEMENT_TYPE_ENTRANCE: - { - auto el = _element->AsEntrance(); - el->SetSequenceIndex(value); - Invalidate(); - break; - } - } - } - - DukValue ride_get() const - { - auto ctx = GetContext()->GetScriptEngine().GetContext(); - switch (_element->GetType()) - { - case TILE_ELEMENT_TYPE_PATH: - { - auto el = _element->AsPath(); - if (el->IsQueue() && el->GetRideIndex() != RIDE_ID_NULL) - duk_push_int(ctx, el->GetRideIndex()); - else - duk_push_null(ctx); - break; - } - case TILE_ELEMENT_TYPE_TRACK: - { - auto el = _element->AsTrack(); - duk_push_int(ctx, el->GetRideIndex()); - break; - } - case TILE_ELEMENT_TYPE_ENTRANCE: - { - auto el = _element->AsEntrance(); - duk_push_int(ctx, el->GetRideIndex()); - break; - } - default: - { - duk_push_null(ctx); - break; - } - } - return DukValue::take_from_stack(ctx); - } - void ride_set(ride_id_t value) - { - ThrowIfGameStateNotMutable(); - switch (_element->GetType()) - { - case TILE_ELEMENT_TYPE_PATH: - { - auto el = _element->AsPath(); - if (!el->HasAddition()) - { - el->SetRideIndex(value); - Invalidate(); - } - break; - } - case TILE_ELEMENT_TYPE_TRACK: - { - auto el = _element->AsTrack(); - el->SetRideIndex(value); - Invalidate(); - break; - } - case TILE_ELEMENT_TYPE_ENTRANCE: - { - auto el = _element->AsEntrance(); - el->SetRideIndex(value); - Invalidate(); - break; - } - } - } - - DukValue station_get() const - { - auto ctx = GetContext()->GetScriptEngine().GetContext(); - switch (_element->GetType()) - { - case TILE_ELEMENT_TYPE_PATH: - { - auto el = _element->AsPath(); - if (el->IsQueue() && el->GetRideIndex() != RIDE_ID_NULL) - duk_push_int(ctx, el->GetStationIndex()); - else - duk_push_null(ctx); - break; - } - case TILE_ELEMENT_TYPE_TRACK: - { - auto el = _element->AsTrack(); - if (el->IsStation()) - duk_push_int(ctx, el->GetStationIndex()); - else - duk_push_null(ctx); - break; - } - case TILE_ELEMENT_TYPE_ENTRANCE: - { - auto el = _element->AsEntrance(); - duk_push_int(ctx, el->GetStationIndex()); - break; - } - default: - { - duk_push_null(ctx); - break; - } - } - return DukValue::take_from_stack(ctx); - } - void station_set(uint8_t value) - { - ThrowIfGameStateNotMutable(); - switch (_element->GetType()) - { - case TILE_ELEMENT_TYPE_PATH: - { - auto el = _element->AsPath(); - el->SetStationIndex(value); - Invalidate(); - break; - } - case TILE_ELEMENT_TYPE_TRACK: - { - auto el = _element->AsTrack(); - el->SetStationIndex(value); - Invalidate(); - break; - } - case TILE_ELEMENT_TYPE_ENTRANCE: - { - auto el = _element->AsEntrance(); - el->SetStationIndex(value); - Invalidate(); - break; - } - } - } - - DukValue hasChainLift_get() const - { - auto ctx = GetContext()->GetScriptEngine().GetContext(); - auto el = _element->AsTrack(); - if (el != nullptr) - duk_push_boolean(ctx, el->HasChain()); - else - duk_push_null(ctx); - return DukValue::take_from_stack(ctx); - } - void hasChainLift_set(bool value) - { - ThrowIfGameStateNotMutable(); - auto el = _element->AsTrack(); - if (el != nullptr) - { - el->SetHasChain(value); - Invalidate(); - } - } - - DukValue mazeEntry_get() const - { - auto ctx = GetContext()->GetScriptEngine().GetContext(); - auto el = _element->AsTrack(); - if (el != nullptr && get_ride(el->GetRideIndex())->type == RIDE_TYPE_MAZE) - duk_push_int(ctx, el->GetMazeEntry()); - else - duk_push_null(ctx); - return DukValue::take_from_stack(ctx); - } - void mazeEntry_set(uint16_t value) - { - ThrowIfGameStateNotMutable(); - auto el = _element->AsTrack(); - if (el != nullptr) - if (get_ride(el->GetRideIndex())->type == RIDE_TYPE_MAZE) - { - el->SetMazeEntry(value); - Invalidate(); - } - } - - DukValue colourScheme_get() const - { - auto ctx = GetContext()->GetScriptEngine().GetContext(); - auto el = _element->AsTrack(); - if (el != nullptr && get_ride(el->GetRideIndex())->type != RIDE_TYPE_MAZE) - duk_push_int(ctx, el->GetColourScheme()); - else - duk_push_null(ctx); - return DukValue::take_from_stack(ctx); - } - void colourScheme_set(uint8_t value) - { - ThrowIfGameStateNotMutable(); - auto el = _element->AsTrack(); - if (el != nullptr) - if (get_ride(el->GetRideIndex())->type != RIDE_TYPE_MAZE) - { - el->SetColourScheme(value); - Invalidate(); - } - } - - DukValue seatRotation_get() const - { - auto ctx = GetContext()->GetScriptEngine().GetContext(); - auto el = _element->AsTrack(); - if (el != nullptr && get_ride(el->GetRideIndex())->type != RIDE_TYPE_MAZE) - duk_push_int(ctx, el->GetSeatRotation()); - else - duk_push_null(ctx); - return DukValue::take_from_stack(ctx); - } - void seatRotation_set(uint8_t value) - { - ThrowIfGameStateNotMutable(); - auto el = _element->AsTrack(); - if (el != nullptr) - if (get_ride(el->GetRideIndex())->type != RIDE_TYPE_MAZE) - { - el->SetSeatRotation(value); - Invalidate(); - } - } - - DukValue brakeBoosterSpeed_get() const - { - auto ctx = GetContext()->GetScriptEngine().GetContext(); - auto el = _element->AsTrack(); - if (el != nullptr && TrackTypeHasSpeedSetting(el->GetTrackType())) - duk_push_int(ctx, el->GetBrakeBoosterSpeed()); - else - duk_push_null(ctx); - return DukValue::take_from_stack(ctx); - } - void brakeBoosterSpeed_set(uint8_t value) - { - ThrowIfGameStateNotMutable(); - auto el = _element->AsTrack(); - if (el != nullptr) - if (TrackTypeHasSpeedSetting(el->GetTrackType())) - { - el->SetBrakeBoosterSpeed(value); - Invalidate(); - } - } - - DukValue isInverted_get() const - { - auto ctx = GetContext()->GetScriptEngine().GetContext(); - auto el = _element->AsTrack(); - if (el != nullptr) - duk_push_boolean(ctx, el->IsInverted()); - else - duk_push_null(ctx); - return DukValue::take_from_stack(ctx); - } - void isInverted_set(bool value) - { - ThrowIfGameStateNotMutable(); - auto el = _element->AsTrack(); - if (el != nullptr) - { - el->SetInverted(value); - Invalidate(); - } - } - - DukValue hasCableLift_get() const - { - auto ctx = GetContext()->GetScriptEngine().GetContext(); - auto el = _element->AsTrack(); - if (el != nullptr) - duk_push_boolean(ctx, el->HasCableLift()); - else - duk_push_null(ctx); - return DukValue::take_from_stack(ctx); - } - void hasCableLift_set(bool value) - { - ThrowIfGameStateNotMutable(); - auto el = _element->AsTrack(); - if (el != nullptr) - { - el->SetHasCableLift(value); - Invalidate(); - } - } - - DukValue object_get() const - { - auto ctx = GetContext()->GetScriptEngine().GetContext(); - switch (_element->GetType()) - { - case TILE_ELEMENT_TYPE_PATH: - { - auto el = _element->AsPath(); - duk_push_int(ctx, el->GetSurfaceEntryIndex()); - break; - } - case TILE_ELEMENT_TYPE_SMALL_SCENERY: - { - auto el = _element->AsSmallScenery(); - duk_push_int(ctx, el->GetEntryIndex()); - break; - } - case TILE_ELEMENT_TYPE_LARGE_SCENERY: - { - auto el = _element->AsLargeScenery(); - duk_push_int(ctx, el->GetEntryIndex()); - break; - } - case TILE_ELEMENT_TYPE_WALL: - { - auto el = _element->AsWall(); - duk_push_int(ctx, el->GetEntryIndex()); - break; - } - case TILE_ELEMENT_TYPE_ENTRANCE: - { - auto el = _element->AsEntrance(); - duk_push_int(ctx, el->GetEntranceType()); - break; - } - default: - { - duk_push_null(ctx); - break; - } - } - return DukValue::take_from_stack(ctx); - } - void object_set(uint32_t value) - { - ThrowIfGameStateNotMutable(); - switch (_element->GetType()) - { - case TILE_ELEMENT_TYPE_PATH: - { - auto el = _element->AsPath(); - el->SetSurfaceEntryIndex(value & 0xFF); - Invalidate(); - break; - } - case TILE_ELEMENT_TYPE_SMALL_SCENERY: - { - auto el = _element->AsSmallScenery(); - el->SetEntryIndex(value & 0xFF); - Invalidate(); - break; - } - case TILE_ELEMENT_TYPE_LARGE_SCENERY: - { - auto el = _element->AsLargeScenery(); - el->SetEntryIndex(value); - Invalidate(); - break; - } - case TILE_ELEMENT_TYPE_WALL: - { - auto el = _element->AsWall(); - el->SetEntryIndex(value & 0xFFFF); - Invalidate(); - break; - } - case TILE_ELEMENT_TYPE_ENTRANCE: - { - auto el = _element->AsEntrance(); - el->SetEntranceType(value & 0xFF); - Invalidate(); - break; - } - } - } - - 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 * COORDS_Z_STEP }, 0, TileElementType::Corrupt); - if (insertedElement == nullptr) - { - // TODO: Show error - return; - } - - // 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(*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--; - } - - Invalidate(); - } - - DukValue age_get() const - { - auto ctx = GetContext()->GetScriptEngine().GetContext(); - auto el = _element->AsSmallScenery(); - if (el != nullptr) - duk_push_int(ctx, el->GetAge()); - else - duk_push_null(ctx); - return DukValue::take_from_stack(ctx); - } - void age_set(uint8_t value) - { - ThrowIfGameStateNotMutable(); - auto el = _element->AsSmallScenery(); - if (el != nullptr) - { - el->SetAge(value); - Invalidate(); - } - } - - DukValue quadrant_get() const - { - auto ctx = GetContext()->GetScriptEngine().GetContext(); - auto el = _element->AsSmallScenery(); - if (el != nullptr) - duk_push_int(ctx, el->GetSceneryQuadrant()); - else - duk_push_null(ctx); - return DukValue::take_from_stack(ctx); - } - void quadrant_set(uint8_t value) - { - ThrowIfGameStateNotMutable(); - auto el = _element->AsSmallScenery(); - if (el != nullptr) - { - el->SetSceneryQuadrant(value); - Invalidate(); - } - } - - uint8_t occupiedQuadrants_get() const - { - return _element->GetOccupiedQuadrants(); - } - void occupiedQuadrants_set(uint8_t value) - { - ThrowIfGameStateNotMutable(); - _element->SetOccupiedQuadrants(value); - Invalidate(); - } - - bool isGhost_get() const - { - return _element->IsGhost(); - } - void isGhost_set(bool value) - { - ThrowIfGameStateNotMutable(); - _element->SetGhost(value); - Invalidate(); - } - - DukValue primaryColour_get() const - { - auto ctx = GetContext()->GetScriptEngine().GetContext(); - switch (_element->GetType()) - { - case TILE_ELEMENT_TYPE_SMALL_SCENERY: - { - auto el = _element->AsSmallScenery(); - duk_push_int(ctx, el->GetPrimaryColour()); - break; - } - case TILE_ELEMENT_TYPE_LARGE_SCENERY: - { - auto el = _element->AsLargeScenery(); - duk_push_int(ctx, el->GetPrimaryColour()); - break; - } - case TILE_ELEMENT_TYPE_WALL: - { - auto el = _element->AsWall(); - duk_push_int(ctx, el->GetPrimaryColour()); - break; - } - default: - { - duk_push_null(ctx); - break; - } - } - return DukValue::take_from_stack(ctx); - } - void primaryColour_set(uint8_t value) - { - ThrowIfGameStateNotMutable(); - switch (_element->GetType()) - { - case TILE_ELEMENT_TYPE_SMALL_SCENERY: - { - auto el = _element->AsSmallScenery(); - el->SetPrimaryColour(value); - Invalidate(); - break; - } - case TILE_ELEMENT_TYPE_LARGE_SCENERY: - { - auto el = _element->AsLargeScenery(); - el->SetPrimaryColour(value); - Invalidate(); - break; - } - case TILE_ELEMENT_TYPE_WALL: - { - auto el = _element->AsWall(); - el->SetPrimaryColour(value); - Invalidate(); - break; - } - } - } - - DukValue secondaryColour_get() const - { - auto ctx = GetContext()->GetScriptEngine().GetContext(); - switch (_element->GetType()) - { - case TILE_ELEMENT_TYPE_SMALL_SCENERY: - { - auto el = _element->AsSmallScenery(); - duk_push_int(ctx, el->GetSecondaryColour()); - break; - } - case TILE_ELEMENT_TYPE_LARGE_SCENERY: - { - auto el = _element->AsLargeScenery(); - duk_push_int(ctx, el->GetSecondaryColour()); - break; - } - case TILE_ELEMENT_TYPE_WALL: - { - auto el = _element->AsWall(); - duk_push_int(ctx, el->GetSecondaryColour()); - break; - } - default: - { - duk_push_null(ctx); - break; - } - } - return DukValue::take_from_stack(ctx); - } - void secondaryColour_set(uint8_t value) - { - ThrowIfGameStateNotMutable(); - switch (_element->GetType()) - { - case TILE_ELEMENT_TYPE_SMALL_SCENERY: - { - auto el = _element->AsSmallScenery(); - el->SetSecondaryColour(value); - Invalidate(); - break; - } - case TILE_ELEMENT_TYPE_LARGE_SCENERY: - { - auto el = _element->AsLargeScenery(); - el->SetSecondaryColour(value); - Invalidate(); - break; - } - case TILE_ELEMENT_TYPE_WALL: - { - auto el = _element->AsWall(); - el->SetSecondaryColour(value); - Invalidate(); - break; - } - } - } - - DukValue tertiaryColour_get() const - { - auto ctx = GetContext()->GetScriptEngine().GetContext(); - auto el = _element->AsWall(); - if (el != nullptr) - duk_push_int(ctx, el->GetTertiaryColour()); - else - duk_push_null(ctx); - return DukValue::take_from_stack(ctx); - } - void tertiaryColour_set(uint8_t value) - { - ThrowIfGameStateNotMutable(); - auto el = _element->AsWall(); - if (el != nullptr) - { - el->SetTertiaryColour(value); - Invalidate(); - } - } - - DukValue bannerIndex_get() const - { - auto ctx = GetContext()->GetScriptEngine().GetContext(); - BannerIndex idx = _element->GetBannerIndex(); - if (idx == BANNER_INDEX_NULL) - duk_push_null(ctx); - else - duk_push_int(ctx, idx); - return DukValue::take_from_stack(ctx); - } - void bannerIndex_set(uint16_t value) - { - ThrowIfGameStateNotMutable(); - switch (_element->GetType()) - { - case TILE_ELEMENT_TYPE_LARGE_SCENERY: - { - auto el = _element->AsLargeScenery(); - el->SetBannerIndex(value); - Invalidate(); - break; - } - case TILE_ELEMENT_TYPE_WALL: - { - auto el = _element->AsWall(); - el->SetBannerIndex(value); - Invalidate(); - break; - } - case TILE_ELEMENT_TYPE_BANNER: - { - auto el = _element->AsBanner(); - el->SetIndex(value); - Invalidate(); - break; - } - } - } - - // Deprecated in favor of seperate 'edges' and 'corners' properties, - // left here to maintain compatibility with older plugins. - /** @deprecated */ - uint8_t edgesAndCorners_get() const - { - auto el = _element->AsPath(); - return el != nullptr ? el->GetEdgesAndCorners() : 0; - } - /** @deprecated */ - void edgesAndCorners_set(uint8_t value) - { - ThrowIfGameStateNotMutable(); - auto el = _element->AsPath(); - if (el != nullptr) - { - el->SetEdgesAndCorners(value); - Invalidate(); - } - } - - DukValue edges_get() const - { - auto ctx = GetContext()->GetScriptEngine().GetContext(); - auto el = _element->AsPath(); - if (el != nullptr) - duk_push_int(ctx, el->GetEdges()); - else - duk_push_null(ctx); - return DukValue::take_from_stack(ctx); - } - void edges_set(uint8_t value) - { - ThrowIfGameStateNotMutable(); - auto el = _element->AsPath(); - if (el != nullptr) - { - el->SetEdges(value); - Invalidate(); - } - } - - DukValue corners_get() const - { - auto ctx = GetContext()->GetScriptEngine().GetContext(); - auto el = _element->AsPath(); - if (el != nullptr) - duk_push_int(ctx, el->GetCorners()); - else - duk_push_null(ctx); - return DukValue::take_from_stack(ctx); - } - void corners_set(uint8_t value) - { - ThrowIfGameStateNotMutable(); - auto el = _element->AsPath(); - if (el != nullptr) - { - el->SetCorners(value); - Invalidate(); - } - } - - DukValue slopeDirection_get() const - { - auto ctx = GetContext()->GetScriptEngine().GetContext(); - auto el = _element->AsPath(); - if (el != nullptr && el->IsSloped()) - duk_push_int(ctx, el->GetSlopeDirection()); - else - duk_push_null(ctx); - return DukValue::take_from_stack(ctx); - } - void slopeDirection_set(const DukValue& value) - { - ThrowIfGameStateNotMutable(); - auto el = _element->AsPath(); - if (el != nullptr) - { - if (value.type() == DukValue::Type::NUMBER) - { - el->SetSloped(true); - el->SetSlopeDirection(value.as_int()); - } - else - { - el->SetSloped(false); - el->SetSlopeDirection(0); - } - Invalidate(); - } - } - - DukValue isQueue_get() const - { - auto ctx = GetContext()->GetScriptEngine().GetContext(); - auto el = _element->AsPath(); - if (el != nullptr) - duk_push_boolean(ctx, el->IsQueue()); - else - duk_push_null(ctx); - return DukValue::take_from_stack(ctx); - } - void isQueue_set(bool value) - { - ThrowIfGameStateNotMutable(); - auto el = _element->AsPath(); - if (el != nullptr) - { - el->SetIsQueue(value); - Invalidate(); - } - } - - DukValue queueBannerDirection_get() const - { - auto ctx = GetContext()->GetScriptEngine().GetContext(); - auto el = _element->AsPath(); - if (el != nullptr && el->HasQueueBanner()) - duk_push_int(ctx, el->GetQueueBannerDirection()); - else - duk_push_null(ctx); - return DukValue::take_from_stack(ctx); - } - void queueBannerDirection_set(const DukValue& value) - { - ThrowIfGameStateNotMutable(); - auto el = _element->AsPath(); - if (el != nullptr) - { - if (value.type() == DukValue::Type::NUMBER) - { - el->SetHasQueueBanner(true); - el->SetQueueBannerDirection(value.as_int()); - } - else - { - el->SetHasQueueBanner(false); - el->SetQueueBannerDirection(0); - } - Invalidate(); - } - } - - DukValue isBlockedByVehicle_get() const - { - auto ctx = GetContext()->GetScriptEngine().GetContext(); - auto el = _element->AsPath(); - if (el != nullptr) - duk_push_boolean(ctx, el->IsBlockedByVehicle()); - else - duk_push_null(ctx); - return DukValue::take_from_stack(ctx); - } - void isBlockedByVehicle_set(bool value) - { - ThrowIfGameStateNotMutable(); - auto el = _element->AsPath(); - if (el != nullptr) - { - el->SetIsBlockedByVehicle(value); - Invalidate(); - } - } - - DukValue isWide_get() const - { - auto ctx = GetContext()->GetScriptEngine().GetContext(); - auto el = _element->AsPath(); - if (el != nullptr) - duk_push_boolean(ctx, el->IsWide()); - else - duk_push_null(ctx); - return DukValue::take_from_stack(ctx); - } - void isWide_set(bool value) - { - ThrowIfGameStateNotMutable(); - auto el = _element->AsPath(); - if (el != nullptr) - { - el->SetWide(value); - Invalidate(); - } - } - - DukValue addition_get() const - { - auto ctx = GetContext()->GetScriptEngine().GetContext(); - auto el = _element->AsPath(); - if (el != nullptr && el->HasAddition()) - duk_push_int(ctx, el->GetAddition() - 1); - else - duk_push_null(ctx); - return DukValue::take_from_stack(ctx); - } - void addition_set(const DukValue& value) - { - ThrowIfGameStateNotMutable(); - auto el = _element->AsPath(); - if (el != nullptr) - { - if (value.type() == DukValue::Type::NUMBER) - { - auto addition = value.as_int(); - if (addition >= 0 && addition <= 254) - { - el->SetAddition(addition + 1); - } - } - else - { - el->SetAddition(0); - } - Invalidate(); - } - } - - DukValue additionStatus_get() const - { - auto ctx = GetContext()->GetScriptEngine().GetContext(); - auto el = _element->AsPath(); - if (el != nullptr && el->HasAddition()) - duk_push_int(ctx, el->GetAdditionStatus()); - else - duk_push_null(ctx); - return DukValue::take_from_stack(ctx); - } - void additionStatus_set(uint8_t value) - { - ThrowIfGameStateNotMutable(); - auto el = _element->AsPath(); - if (el != nullptr) - if (el->HasAddition()) - { - el->SetAdditionStatus(value); - Invalidate(); - } - } - - DukValue isAdditionBroken_get() const - { - auto ctx = GetContext()->GetScriptEngine().GetContext(); - auto el = _element->AsPath(); - if (el != nullptr && el->HasAddition()) - duk_push_boolean(ctx, el->IsBroken()); - else - duk_push_null(ctx); - return DukValue::take_from_stack(ctx); - } - void isAdditionBroken_set(bool value) - { - ThrowIfGameStateNotMutable(); - auto el = _element->AsPath(); - if (el != nullptr) - { - el->SetIsBroken(value); - Invalidate(); - } - } - - DukValue isAdditionGhost_get() const - { - auto ctx = GetContext()->GetScriptEngine().GetContext(); - auto el = _element->AsPath(); - if (el != nullptr && el->HasAddition()) - duk_push_boolean(ctx, el->AdditionIsGhost()); - else - duk_push_null(ctx); - return DukValue::take_from_stack(ctx); - } - void isAdditionGhost_set(bool value) - { - ThrowIfGameStateNotMutable(); - auto el = _element->AsPath(); - if (el != nullptr) - { - el->SetAdditionIsGhost(value); - Invalidate(); - } - } - - DukValue footpathObject_get() const - { - auto ctx = GetContext()->GetScriptEngine().GetContext(); - auto el = _element->AsEntrance(); - if (el != nullptr) - duk_push_int(ctx, el->GetPathType()); - else - duk_push_null(ctx); - return DukValue::take_from_stack(ctx); - } - void footpathObject_set(uint8_t value) - { - ThrowIfGameStateNotMutable(); - auto el = _element->AsEntrance(); - if (el != nullptr) - { - el->SetPathType(value); - Invalidate(); - } - } - - DukValue direction_get() const - { - auto ctx = GetContext()->GetScriptEngine().GetContext(); - switch (_element->GetType()) - { - case TILE_ELEMENT_TYPE_BANNER: - { - auto el = _element->AsBanner(); - duk_push_int(ctx, el->GetPosition()); - break; - } - case TILE_ELEMENT_TYPE_PATH: - case TILE_ELEMENT_TYPE_SURFACE: - { - duk_push_null(ctx); - break; - } - default: - { - duk_push_int(ctx, _element->GetDirection()); - break; - } - } - return DukValue::take_from_stack(ctx); - } - void direction_set(uint8_t value) - { - ThrowIfGameStateNotMutable(); - switch (_element->GetType()) - { - case TILE_ELEMENT_TYPE_BANNER: - { - auto el = _element->AsBanner(); - el->SetPosition(value); - Invalidate(); - break; - } - case TILE_ELEMENT_TYPE_PATH: - case TILE_ELEMENT_TYPE_SURFACE: - { - break; - } - default: - { - _element->SetDirection(value); - Invalidate(); - } - } - } - - void Invalidate() - { - map_invalidate_tile_full(_coords); - } - - public: - static void Register(duk_context* ctx) - { - // All - dukglue_register_property(ctx, &ScTileElement::type_get, &ScTileElement::type_set, "type"); - dukglue_register_property(ctx, &ScTileElement::baseHeight_get, &ScTileElement::baseHeight_set, "baseHeight"); - dukglue_register_property(ctx, &ScTileElement::baseZ_get, &ScTileElement::baseZ_set, "baseZ"); - dukglue_register_property( - ctx, &ScTileElement::clearanceHeight_get, &ScTileElement::clearanceHeight_set, "clearanceHeight"); - dukglue_register_property(ctx, &ScTileElement::clearanceZ_get, &ScTileElement::clearanceZ_set, "clearanceZ"); - dukglue_register_property( - ctx, &ScTileElement::occupiedQuadrants_get, &ScTileElement::occupiedQuadrants_set, "occupiedQuadrants"); - dukglue_register_property(ctx, &ScTileElement::isGhost_get, &ScTileElement::isGhost_set, "isGhost"); - dukglue_register_property(ctx, &ScTileElement::isHidden_get, &ScTileElement::isHidden_set, "isHidden"); - - // 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 - dukglue_register_property(ctx, &ScTileElement::object_get, &ScTileElement::object_set, "object"); - - // Small Scenery | Wall | Large Scenery - dukglue_register_property( - ctx, &ScTileElement::primaryColour_get, &ScTileElement::primaryColour_set, "primaryColour"); - dukglue_register_property( - ctx, &ScTileElement::secondaryColour_get, &ScTileElement::secondaryColour_set, "secondaryColour"); - - // Wall | Large Scenery | Banner - dukglue_register_property(ctx, &ScTileElement::bannerIndex_get, &ScTileElement::bannerIndex_set, "bannerIndex"); - - // Path | Track | Entrance - dukglue_register_property(ctx, &ScTileElement::ride_get, &ScTileElement::ride_set, "ride"); - dukglue_register_property(ctx, &ScTileElement::station_get, &ScTileElement::station_set, "station"); - - // Track | Entrance | Large Scenery - dukglue_register_property(ctx, &ScTileElement::sequence_get, &ScTileElement::sequence_set, "sequence"); - - // Surface | Wall - dukglue_register_property(ctx, &ScTileElement::slope_get, &ScTileElement::slope_set, "slope"); - - // Surface only - dukglue_register_property(ctx, &ScTileElement::waterHeight_get, &ScTileElement::waterHeight_set, "waterHeight"); - dukglue_register_property(ctx, &ScTileElement::surfaceStyle_get, &ScTileElement::surfaceStyle_set, "surfaceStyle"); - dukglue_register_property(ctx, &ScTileElement::edgeStyle_get, &ScTileElement::edgeStyle_set, "edgeStyle"); - dukglue_register_property(ctx, &ScTileElement::grassLength_get, &ScTileElement::grassLength_set, "grassLength"); - dukglue_register_property(ctx, &ScTileElement::hasOwnership_get, nullptr, "hasOwnership"); - dukglue_register_property(ctx, &ScTileElement::hasConstructionRights_get, nullptr, "hasConstructionRights"); - dukglue_register_property(ctx, &ScTileElement::ownership_get, &ScTileElement::ownership_set, "ownership"); - dukglue_register_property(ctx, &ScTileElement::parkFences_get, &ScTileElement::parkFences_set, "parkFences"); - - // Footpath only - dukglue_register_property( - ctx, &ScTileElement::edgesAndCorners_get, &ScTileElement::edgesAndCorners_set, "edgesAndCorners"); - dukglue_register_property(ctx, &ScTileElement::edges_get, &ScTileElement::edges_set, "edges"); - dukglue_register_property(ctx, &ScTileElement::corners_get, &ScTileElement::corners_set, "corners"); - dukglue_register_property( - ctx, &ScTileElement::slopeDirection_get, &ScTileElement::slopeDirection_set, "slopeDirection"); - dukglue_register_property(ctx, &ScTileElement::isQueue_get, &ScTileElement::isQueue_set, "isQueue"); - dukglue_register_property( - ctx, &ScTileElement::queueBannerDirection_get, &ScTileElement::queueBannerDirection_set, - "queueBannerDirection"); - dukglue_register_property(ctx, &ScTileElement::queueBannerDirection_get, &ScTileElement::edges_set, "test"); - - dukglue_register_property( - ctx, &ScTileElement::isBlockedByVehicle_get, &ScTileElement::isBlockedByVehicle_set, "isBlockedByVehicle"); - dukglue_register_property(ctx, &ScTileElement::isWide_get, &ScTileElement::isWide_set, "isWide"); - - dukglue_register_property(ctx, &ScTileElement::addition_get, &ScTileElement::addition_set, "addition"); - dukglue_register_property( - ctx, &ScTileElement::additionStatus_get, &ScTileElement::additionStatus_set, "additionStatus"); - dukglue_register_property( - ctx, &ScTileElement::isAdditionBroken_get, &ScTileElement::isAdditionBroken_set, "isAdditionBroken"); - dukglue_register_property( - ctx, &ScTileElement::isAdditionGhost_get, &ScTileElement::isAdditionGhost_set, "isAdditionGhost"); - - // Track only - dukglue_register_property(ctx, &ScTileElement::trackType_get, &ScTileElement::trackType_set, "trackType"); - dukglue_register_property(ctx, &ScTileElement::mazeEntry_get, &ScTileElement::mazeEntry_set, "mazeEntry"); - dukglue_register_property(ctx, &ScTileElement::colourScheme_get, &ScTileElement::colourScheme_set, "colourScheme"); - dukglue_register_property(ctx, &ScTileElement::seatRotation_get, &ScTileElement::seatRotation_set, "seatRotation"); - dukglue_register_property( - ctx, &ScTileElement::brakeBoosterSpeed_get, &ScTileElement::brakeBoosterSpeed_set, "brakeBoosterSpeed"); - dukglue_register_property(ctx, &ScTileElement::hasChainLift_get, &ScTileElement::hasChainLift_set, "hasChainLift"); - dukglue_register_property(ctx, &ScTileElement::isInverted_get, &ScTileElement::isInverted_set, "isInverted"); - dukglue_register_property(ctx, &ScTileElement::hasCableLift_get, &ScTileElement::hasCableLift_set, "hasCableLift"); - - // Small Scenery only - dukglue_register_property(ctx, &ScTileElement::age_get, &ScTileElement::age_set, "age"); - dukglue_register_property(ctx, &ScTileElement::quadrant_get, &ScTileElement::quadrant_set, "quadrant"); - - // Wall only - dukglue_register_property( - ctx, &ScTileElement::tertiaryColour_get, &ScTileElement::tertiaryColour_set, "tertiaryColour"); - - // Entrance only - dukglue_register_property( - ctx, &ScTileElement::footpathObject_get, &ScTileElement::footpathObject_set, "footpathObject"); - } - }; - class ScTile { private: diff --git a/src/openrct2/scripting/bindings/world/ScTileElement.cpp b/src/openrct2/scripting/bindings/world/ScTileElement.cpp new file mode 100644 index 0000000000..40251c55a4 --- /dev/null +++ b/src/openrct2/scripting/bindings/world/ScTileElement.cpp @@ -0,0 +1,1569 @@ +/***************************************************************************** + * Copyright (c) 2014-2021 OpenRCT2 developers + * + * For a complete list of all authors, please refer to contributors.md + * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 is licensed under the GNU General Public License version 3. + *****************************************************************************/ + +#ifdef ENABLE_SCRIPTING + +# include "ScTileElement.hpp" + +# include "../../../Context.h" +# include "../../../common.h" +# include "../../../core/Guard.hpp" +# include "../../../ride/Track.h" +# include "../../../world/Footpath.h" +# include "../../../world/Scenery.h" +# include "../../../world/Sprite.h" +# include "../../../world/Surface.h" +# include "../../Duktape.hpp" +# include "../../ScriptEngine.h" + +# include +# include +# include + +namespace OpenRCT2::Scripting +{ + ScTileElement::ScTileElement(const CoordsXY& coords, TileElement* element) + : _coords(coords) + , _element(element) + { + } + + std::string ScTileElement::type_get() const + { + switch (_element->GetType()) + { + case TILE_ELEMENT_TYPE_SURFACE: + return "surface"; + case TILE_ELEMENT_TYPE_PATH: + return "footpath"; + case TILE_ELEMENT_TYPE_TRACK: + return "track"; + case TILE_ELEMENT_TYPE_SMALL_SCENERY: + return "small_scenery"; + case TILE_ELEMENT_TYPE_ENTRANCE: + return "entrance"; + case TILE_ELEMENT_TYPE_WALL: + return "wall"; + case TILE_ELEMENT_TYPE_LARGE_SCENERY: + return "large_scenery"; + case TILE_ELEMENT_TYPE_BANNER: + return "banner"; + case TILE_ELEMENT_TYPE_CORRUPT: + return "openrct2_corrupt_deprecated"; + default: + return "unknown"; + } + } + + void ScTileElement::type_set(std::string value) + { + auto type = _element->type; + if (value == "surface") + type = TILE_ELEMENT_TYPE_SURFACE; + else if (value == "footpath") + type = TILE_ELEMENT_TYPE_PATH; + else if (value == "track") + type = TILE_ELEMENT_TYPE_TRACK; + else if (value == "small_scenery") + type = TILE_ELEMENT_TYPE_SMALL_SCENERY; + else if (value == "entrance") + type = TILE_ELEMENT_TYPE_ENTRANCE; + else if (value == "wall") + type = TILE_ELEMENT_TYPE_WALL; + else if (value == "large_scenery") + type = TILE_ELEMENT_TYPE_LARGE_SCENERY; + else if (value == "banner") + type = TILE_ELEMENT_TYPE_BANNER; + 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; + Invalidate(); + } + + uint8_t ScTileElement::baseHeight_get() const + { + return _element->base_height; + } + void ScTileElement::baseHeight_set(uint8_t newBaseHeight) + { + ThrowIfGameStateNotMutable(); + _element->base_height = newBaseHeight; + Invalidate(); + } + + uint16_t ScTileElement::baseZ_get() const + { + return _element->GetBaseZ(); + } + void ScTileElement::baseZ_set(uint16_t value) + { + ThrowIfGameStateNotMutable(); + _element->SetBaseZ(value); + Invalidate(); + } + + uint8_t ScTileElement::clearanceHeight_get() const + { + return _element->clearance_height; + } + void ScTileElement::clearanceHeight_set(uint8_t newClearanceHeight) + { + ThrowIfGameStateNotMutable(); + _element->clearance_height = newClearanceHeight; + Invalidate(); + } + + uint16_t ScTileElement::clearanceZ_get() const + { + return _element->GetClearanceZ(); + } + void ScTileElement::clearanceZ_set(uint16_t value) + { + ThrowIfGameStateNotMutable(); + _element->SetClearanceZ(value); + Invalidate(); + } + + DukValue ScTileElement::slope_get() const + { + auto ctx = GetContext()->GetScriptEngine().GetContext(); + switch (_element->GetType()) + { + case TILE_ELEMENT_TYPE_SURFACE: + { + auto el = _element->AsSurface(); + duk_push_int(ctx, el->GetSlope()); + break; + } + case TILE_ELEMENT_TYPE_WALL: + { + auto el = _element->AsWall(); + duk_push_int(ctx, el->GetSlope()); + break; + } + default: + { + duk_push_null(ctx); + break; + } + } + return DukValue::take_from_stack(ctx); + } + void ScTileElement::slope_set(uint8_t value) + { + ThrowIfGameStateNotMutable(); + switch (_element->GetType()) + { + case TILE_ELEMENT_TYPE_SURFACE: + { + auto el = _element->AsSurface(); + el->SetSlope(value); + Invalidate(); + break; + } + case TILE_ELEMENT_TYPE_WALL: + { + auto el = _element->AsWall(); + el->SetSlope(value); + Invalidate(); + break; + } + } + } + + DukValue ScTileElement::waterHeight_get() const + { + auto ctx = GetContext()->GetScriptEngine().GetContext(); + auto el = _element->AsSurface(); + if (el != nullptr) + duk_push_int(ctx, el->GetWaterHeight()); + else + duk_push_null(ctx); + return DukValue::take_from_stack(ctx); + } + void ScTileElement::waterHeight_set(int32_t value) + { + ThrowIfGameStateNotMutable(); + auto el = _element->AsSurface(); + if (el != nullptr) + { + el->SetWaterHeight(value); + Invalidate(); + } + } + + DukValue ScTileElement::surfaceStyle_get() const + { + auto ctx = GetContext()->GetScriptEngine().GetContext(); + auto el = _element->AsSurface(); + if (el != nullptr) + duk_push_int(ctx, el->GetSurfaceStyle()); + else + duk_push_null(ctx); + return DukValue::take_from_stack(ctx); + } + void ScTileElement::surfaceStyle_set(uint32_t value) + { + ThrowIfGameStateNotMutable(); + auto el = _element->AsSurface(); + if (el != nullptr) + { + el->SetSurfaceStyle(value); + Invalidate(); + } + } + + DukValue ScTileElement::edgeStyle_get() const + { + auto ctx = GetContext()->GetScriptEngine().GetContext(); + auto el = _element->AsSurface(); + if (el != nullptr) + duk_push_int(ctx, el->GetEdgeStyle()); + else + duk_push_null(ctx); + return DukValue::take_from_stack(ctx); + } + void ScTileElement::edgeStyle_set(uint32_t value) + { + ThrowIfGameStateNotMutable(); + auto el = _element->AsSurface(); + if (el != nullptr) + { + el->SetEdgeStyle(value); + Invalidate(); + } + } + + DukValue ScTileElement::grassLength_get() const + { + auto ctx = GetContext()->GetScriptEngine().GetContext(); + auto el = _element->AsSurface(); + if (el != nullptr) + duk_push_int(ctx, el->GetGrassLength()); + else + duk_push_null(ctx); + return DukValue::take_from_stack(ctx); + } + void ScTileElement::grassLength_set(uint8_t value) + { + ThrowIfGameStateNotMutable(); + auto el = _element->AsSurface(); + if (el != nullptr) + { + // TODO: Give warning when value > GRASS_LENGTH_CLUMPS_2 + el->SetGrassLengthAndInvalidate(value, _coords); + Invalidate(); + } + } + + DukValue ScTileElement::hasOwnership_get() const + { + auto ctx = GetContext()->GetScriptEngine().GetContext(); + auto el = _element->AsSurface(); + if (el != nullptr) + duk_push_boolean(ctx, el->GetOwnership() & OWNERSHIP_OWNED); + else + duk_push_null(ctx); + return DukValue::take_from_stack(ctx); + } + + DukValue ScTileElement::hasConstructionRights_get() + { + auto ctx = GetContext()->GetScriptEngine().GetContext(); + auto el = _element->AsSurface(); + if (el != nullptr) + { + auto ownership = el->GetOwnership(); + duk_push_boolean(ctx, (ownership & OWNERSHIP_OWNED) || (ownership & OWNERSHIP_CONSTRUCTION_RIGHTS_OWNED)); + } + else + duk_push_null(ctx); + return DukValue::take_from_stack(ctx); + } + + DukValue ScTileElement::ownership_get() const + { + auto ctx = GetContext()->GetScriptEngine().GetContext(); + auto el = _element->AsSurface(); + if (el != nullptr) + duk_push_int(ctx, el->GetOwnership()); + else + duk_push_null(ctx); + return DukValue::take_from_stack(ctx); + } + void ScTileElement::ownership_set(uint8_t value) + { + ThrowIfGameStateNotMutable(); + auto el = _element->AsSurface(); + if (el != nullptr) + { + el->SetOwnership(value); + Invalidate(); + } + } + + DukValue ScTileElement::parkFences_get() const + { + auto ctx = GetContext()->GetScriptEngine().GetContext(); + auto el = _element->AsSurface(); + if (el != nullptr) + duk_push_int(ctx, el->GetParkFences()); + else + duk_push_null(ctx); + return DukValue::take_from_stack(ctx); + } + void ScTileElement::parkFences_set(uint8_t value) + { + ThrowIfGameStateNotMutable(); + auto el = _element->AsSurface(); + if (el != nullptr) + { + el->SetParkFences(value); + Invalidate(); + } + } + + DukValue ScTileElement::trackType_get() const + { + auto ctx = GetContext()->GetScriptEngine().GetContext(); + auto el = _element->AsTrack(); + if (el != nullptr) + duk_push_int(ctx, el->GetTrackType()); + else + duk_push_null(ctx); + return DukValue::take_from_stack(ctx); + } + void ScTileElement::trackType_set(uint8_t value) + { + ThrowIfGameStateNotMutable(); + auto el = _element->AsTrack(); + if (el != nullptr) + { + el->SetTrackType(value); + Invalidate(); + } + } + + DukValue ScTileElement::sequence_get() const + { + auto ctx = GetContext()->GetScriptEngine().GetContext(); + switch (_element->GetType()) + { + case TILE_ELEMENT_TYPE_LARGE_SCENERY: + { + auto el = _element->AsLargeScenery(); + duk_push_int(ctx, el->GetSequenceIndex()); + break; + } + case TILE_ELEMENT_TYPE_TRACK: + { + auto el = _element->AsTrack(); + if (get_ride(el->GetRideIndex())->type != RIDE_TYPE_MAZE) + duk_push_int(ctx, el->GetSequenceIndex()); + else + duk_push_null(ctx); + break; + } + case TILE_ELEMENT_TYPE_ENTRANCE: + { + auto el = _element->AsEntrance(); + duk_push_int(ctx, el->GetSequenceIndex()); + break; + } + default: + { + duk_push_null(ctx); + break; + } + } + return DukValue::take_from_stack(ctx); + } + void ScTileElement::sequence_set(uint8_t value) + { + ThrowIfGameStateNotMutable(); + switch (_element->GetType()) + { + case TILE_ELEMENT_TYPE_LARGE_SCENERY: + { + auto el = _element->AsLargeScenery(); + el->SetSequenceIndex(value); + Invalidate(); + break; + } + case TILE_ELEMENT_TYPE_TRACK: + { + auto el = _element->AsTrack(); + if (get_ride(el->GetRideIndex())->type != RIDE_TYPE_MAZE) + { + el->SetSequenceIndex(value); + Invalidate(); + } + break; + } + case TILE_ELEMENT_TYPE_ENTRANCE: + { + auto el = _element->AsEntrance(); + el->SetSequenceIndex(value); + Invalidate(); + break; + } + } + } + + DukValue ScTileElement::ride_get() const + { + auto ctx = GetContext()->GetScriptEngine().GetContext(); + switch (_element->GetType()) + { + case TILE_ELEMENT_TYPE_PATH: + { + auto el = _element->AsPath(); + if (el->IsQueue() && el->GetRideIndex() != RIDE_ID_NULL) + duk_push_int(ctx, el->GetRideIndex()); + else + duk_push_null(ctx); + break; + } + case TILE_ELEMENT_TYPE_TRACK: + { + auto el = _element->AsTrack(); + duk_push_int(ctx, el->GetRideIndex()); + break; + } + case TILE_ELEMENT_TYPE_ENTRANCE: + { + auto el = _element->AsEntrance(); + duk_push_int(ctx, el->GetRideIndex()); + break; + } + default: + { + duk_push_null(ctx); + break; + } + } + return DukValue::take_from_stack(ctx); + } + void ScTileElement::ride_set(ride_id_t value) + { + ThrowIfGameStateNotMutable(); + switch (_element->GetType()) + { + case TILE_ELEMENT_TYPE_PATH: + { + auto el = _element->AsPath(); + if (!el->HasAddition()) + { + el->SetRideIndex(value); + Invalidate(); + } + break; + } + case TILE_ELEMENT_TYPE_TRACK: + { + auto el = _element->AsTrack(); + el->SetRideIndex(value); + Invalidate(); + break; + } + case TILE_ELEMENT_TYPE_ENTRANCE: + { + auto el = _element->AsEntrance(); + el->SetRideIndex(value); + Invalidate(); + break; + } + } + } + + DukValue ScTileElement::station_get() const + { + auto ctx = GetContext()->GetScriptEngine().GetContext(); + switch (_element->GetType()) + { + case TILE_ELEMENT_TYPE_PATH: + { + auto el = _element->AsPath(); + if (el->IsQueue() && el->GetRideIndex() != RIDE_ID_NULL) + duk_push_int(ctx, el->GetStationIndex()); + else + duk_push_null(ctx); + break; + } + case TILE_ELEMENT_TYPE_TRACK: + { + auto el = _element->AsTrack(); + if (el->IsStation()) + duk_push_int(ctx, el->GetStationIndex()); + else + duk_push_null(ctx); + break; + } + case TILE_ELEMENT_TYPE_ENTRANCE: + { + auto el = _element->AsEntrance(); + duk_push_int(ctx, el->GetStationIndex()); + break; + } + default: + { + duk_push_null(ctx); + break; + } + } + return DukValue::take_from_stack(ctx); + } + void ScTileElement::station_set(uint8_t value) + { + ThrowIfGameStateNotMutable(); + switch (_element->GetType()) + { + case TILE_ELEMENT_TYPE_PATH: + { + auto el = _element->AsPath(); + el->SetStationIndex(value); + Invalidate(); + break; + } + case TILE_ELEMENT_TYPE_TRACK: + { + auto el = _element->AsTrack(); + el->SetStationIndex(value); + Invalidate(); + break; + } + case TILE_ELEMENT_TYPE_ENTRANCE: + { + auto el = _element->AsEntrance(); + el->SetStationIndex(value); + Invalidate(); + break; + } + } + } + + DukValue ScTileElement::hasChainLift_get() const + { + auto ctx = GetContext()->GetScriptEngine().GetContext(); + auto el = _element->AsTrack(); + if (el != nullptr) + duk_push_boolean(ctx, el->HasChain()); + else + duk_push_null(ctx); + return DukValue::take_from_stack(ctx); + } + void ScTileElement::hasChainLift_set(bool value) + { + ThrowIfGameStateNotMutable(); + auto el = _element->AsTrack(); + if (el != nullptr) + { + el->SetHasChain(value); + Invalidate(); + } + } + + DukValue ScTileElement::mazeEntry_get() const + { + auto ctx = GetContext()->GetScriptEngine().GetContext(); + auto el = _element->AsTrack(); + if (el != nullptr && get_ride(el->GetRideIndex())->type == RIDE_TYPE_MAZE) + duk_push_int(ctx, el->GetMazeEntry()); + else + duk_push_null(ctx); + return DukValue::take_from_stack(ctx); + } + void ScTileElement::mazeEntry_set(uint16_t value) + { + ThrowIfGameStateNotMutable(); + auto el = _element->AsTrack(); + if (el != nullptr) + if (get_ride(el->GetRideIndex())->type == RIDE_TYPE_MAZE) + { + el->SetMazeEntry(value); + Invalidate(); + } + } + + DukValue ScTileElement::colourScheme_get() const + { + auto ctx = GetContext()->GetScriptEngine().GetContext(); + auto el = _element->AsTrack(); + if (el != nullptr && get_ride(el->GetRideIndex())->type != RIDE_TYPE_MAZE) + duk_push_int(ctx, el->GetColourScheme()); + else + duk_push_null(ctx); + return DukValue::take_from_stack(ctx); + } + void ScTileElement::colourScheme_set(uint8_t value) + { + ThrowIfGameStateNotMutable(); + auto el = _element->AsTrack(); + if (el != nullptr) + if (get_ride(el->GetRideIndex())->type != RIDE_TYPE_MAZE) + { + el->SetColourScheme(value); + Invalidate(); + } + } + + DukValue ScTileElement::seatRotation_get() const + { + auto ctx = GetContext()->GetScriptEngine().GetContext(); + auto el = _element->AsTrack(); + if (el != nullptr && get_ride(el->GetRideIndex())->type != RIDE_TYPE_MAZE) + duk_push_int(ctx, el->GetSeatRotation()); + else + duk_push_null(ctx); + return DukValue::take_from_stack(ctx); + } + void ScTileElement::seatRotation_set(uint8_t value) + { + ThrowIfGameStateNotMutable(); + auto el = _element->AsTrack(); + if (el != nullptr) + if (get_ride(el->GetRideIndex())->type != RIDE_TYPE_MAZE) + { + el->SetSeatRotation(value); + Invalidate(); + } + } + + DukValue ScTileElement::brakeBoosterSpeed_get() const + { + auto ctx = GetContext()->GetScriptEngine().GetContext(); + auto el = _element->AsTrack(); + if (el != nullptr && TrackTypeHasSpeedSetting(el->GetTrackType())) + duk_push_int(ctx, el->GetBrakeBoosterSpeed()); + else + duk_push_null(ctx); + return DukValue::take_from_stack(ctx); + } + void ScTileElement::brakeBoosterSpeed_set(uint8_t value) + { + ThrowIfGameStateNotMutable(); + auto el = _element->AsTrack(); + if (el != nullptr) + if (TrackTypeHasSpeedSetting(el->GetTrackType())) + { + el->SetBrakeBoosterSpeed(value); + Invalidate(); + } + } + + DukValue ScTileElement::isInverted_get() const + { + auto ctx = GetContext()->GetScriptEngine().GetContext(); + auto el = _element->AsTrack(); + if (el != nullptr) + duk_push_boolean(ctx, el->IsInverted()); + else + duk_push_null(ctx); + return DukValue::take_from_stack(ctx); + } + void ScTileElement::isInverted_set(bool value) + { + ThrowIfGameStateNotMutable(); + auto el = _element->AsTrack(); + if (el != nullptr) + { + el->SetInverted(value); + Invalidate(); + } + } + + DukValue ScTileElement::hasCableLift_get() const + { + auto ctx = GetContext()->GetScriptEngine().GetContext(); + auto el = _element->AsTrack(); + if (el != nullptr) + duk_push_boolean(ctx, el->HasCableLift()); + else + duk_push_null(ctx); + return DukValue::take_from_stack(ctx); + } + void ScTileElement::hasCableLift_set(bool value) + { + ThrowIfGameStateNotMutable(); + auto el = _element->AsTrack(); + if (el != nullptr) + { + el->SetHasCableLift(value); + Invalidate(); + } + } + + DukValue ScTileElement::object_get() const + { + auto ctx = GetContext()->GetScriptEngine().GetContext(); + switch (_element->GetType()) + { + case TILE_ELEMENT_TYPE_PATH: + { + auto el = _element->AsPath(); + duk_push_int(ctx, el->GetSurfaceEntryIndex()); + break; + } + case TILE_ELEMENT_TYPE_SMALL_SCENERY: + { + auto el = _element->AsSmallScenery(); + duk_push_int(ctx, el->GetEntryIndex()); + break; + } + case TILE_ELEMENT_TYPE_LARGE_SCENERY: + { + auto el = _element->AsLargeScenery(); + duk_push_int(ctx, el->GetEntryIndex()); + break; + } + case TILE_ELEMENT_TYPE_WALL: + { + auto el = _element->AsWall(); + duk_push_int(ctx, el->GetEntryIndex()); + break; + } + case TILE_ELEMENT_TYPE_ENTRANCE: + { + auto el = _element->AsEntrance(); + duk_push_int(ctx, el->GetEntranceType()); + break; + } + default: + { + duk_push_null(ctx); + break; + } + } + return DukValue::take_from_stack(ctx); + } + void ScTileElement::object_set(uint32_t value) + { + ThrowIfGameStateNotMutable(); + switch (_element->GetType()) + { + case TILE_ELEMENT_TYPE_PATH: + { + auto el = _element->AsPath(); + el->SetSurfaceEntryIndex(value & 0xFF); + Invalidate(); + break; + } + case TILE_ELEMENT_TYPE_SMALL_SCENERY: + { + auto el = _element->AsSmallScenery(); + el->SetEntryIndex(value & 0xFF); + Invalidate(); + break; + } + case TILE_ELEMENT_TYPE_LARGE_SCENERY: + { + auto el = _element->AsLargeScenery(); + el->SetEntryIndex(value); + Invalidate(); + break; + } + case TILE_ELEMENT_TYPE_WALL: + { + auto el = _element->AsWall(); + el->SetEntryIndex(value & 0xFFFF); + Invalidate(); + break; + } + case TILE_ELEMENT_TYPE_ENTRANCE: + { + auto el = _element->AsEntrance(); + el->SetEntranceType(value & 0xFF); + Invalidate(); + break; + } + } + } + + bool ScTileElement::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 ScTileElement::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 * COORDS_Z_STEP }, 0, TileElementType::Corrupt); + if (insertedElement == nullptr) + { + // TODO: Show error + return; + } + + // 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(*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--; + } + + Invalidate(); + } + + DukValue ScTileElement::age_get() const + { + auto ctx = GetContext()->GetScriptEngine().GetContext(); + auto el = _element->AsSmallScenery(); + if (el != nullptr) + duk_push_int(ctx, el->GetAge()); + else + duk_push_null(ctx); + return DukValue::take_from_stack(ctx); + } + void ScTileElement::age_set(uint8_t value) + { + ThrowIfGameStateNotMutable(); + auto el = _element->AsSmallScenery(); + if (el != nullptr) + { + el->SetAge(value); + Invalidate(); + } + } + + DukValue ScTileElement::quadrant_get() const + { + auto ctx = GetContext()->GetScriptEngine().GetContext(); + auto el = _element->AsSmallScenery(); + if (el != nullptr) + duk_push_int(ctx, el->GetSceneryQuadrant()); + else + duk_push_null(ctx); + return DukValue::take_from_stack(ctx); + } + void ScTileElement::quadrant_set(uint8_t value) + { + ThrowIfGameStateNotMutable(); + auto el = _element->AsSmallScenery(); + if (el != nullptr) + { + el->SetSceneryQuadrant(value); + Invalidate(); + } + } + + uint8_t ScTileElement::occupiedQuadrants_get() const + { + return _element->GetOccupiedQuadrants(); + } + void ScTileElement::occupiedQuadrants_set(uint8_t value) + { + ThrowIfGameStateNotMutable(); + _element->SetOccupiedQuadrants(value); + Invalidate(); + } + + bool ScTileElement::isGhost_get() const + { + return _element->IsGhost(); + } + void ScTileElement::isGhost_set(bool value) + { + ThrowIfGameStateNotMutable(); + _element->SetGhost(value); + Invalidate(); + } + + DukValue ScTileElement::primaryColour_get() const + { + auto ctx = GetContext()->GetScriptEngine().GetContext(); + switch (_element->GetType()) + { + case TILE_ELEMENT_TYPE_SMALL_SCENERY: + { + auto el = _element->AsSmallScenery(); + duk_push_int(ctx, el->GetPrimaryColour()); + break; + } + case TILE_ELEMENT_TYPE_LARGE_SCENERY: + { + auto el = _element->AsLargeScenery(); + duk_push_int(ctx, el->GetPrimaryColour()); + break; + } + case TILE_ELEMENT_TYPE_WALL: + { + auto el = _element->AsWall(); + duk_push_int(ctx, el->GetPrimaryColour()); + break; + } + default: + { + duk_push_null(ctx); + break; + } + } + return DukValue::take_from_stack(ctx); + } + void ScTileElement::primaryColour_set(uint8_t value) + { + ThrowIfGameStateNotMutable(); + switch (_element->GetType()) + { + case TILE_ELEMENT_TYPE_SMALL_SCENERY: + { + auto el = _element->AsSmallScenery(); + el->SetPrimaryColour(value); + Invalidate(); + break; + } + case TILE_ELEMENT_TYPE_LARGE_SCENERY: + { + auto el = _element->AsLargeScenery(); + el->SetPrimaryColour(value); + Invalidate(); + break; + } + case TILE_ELEMENT_TYPE_WALL: + { + auto el = _element->AsWall(); + el->SetPrimaryColour(value); + Invalidate(); + break; + } + } + } + + DukValue ScTileElement::secondaryColour_get() const + { + auto ctx = GetContext()->GetScriptEngine().GetContext(); + switch (_element->GetType()) + { + case TILE_ELEMENT_TYPE_SMALL_SCENERY: + { + auto el = _element->AsSmallScenery(); + duk_push_int(ctx, el->GetSecondaryColour()); + break; + } + case TILE_ELEMENT_TYPE_LARGE_SCENERY: + { + auto el = _element->AsLargeScenery(); + duk_push_int(ctx, el->GetSecondaryColour()); + break; + } + case TILE_ELEMENT_TYPE_WALL: + { + auto el = _element->AsWall(); + duk_push_int(ctx, el->GetSecondaryColour()); + break; + } + default: + { + duk_push_null(ctx); + break; + } + } + return DukValue::take_from_stack(ctx); + } + void ScTileElement::secondaryColour_set(uint8_t value) + { + ThrowIfGameStateNotMutable(); + switch (_element->GetType()) + { + case TILE_ELEMENT_TYPE_SMALL_SCENERY: + { + auto el = _element->AsSmallScenery(); + el->SetSecondaryColour(value); + Invalidate(); + break; + } + case TILE_ELEMENT_TYPE_LARGE_SCENERY: + { + auto el = _element->AsLargeScenery(); + el->SetSecondaryColour(value); + Invalidate(); + break; + } + case TILE_ELEMENT_TYPE_WALL: + { + auto el = _element->AsWall(); + el->SetSecondaryColour(value); + Invalidate(); + break; + } + } + } + + DukValue ScTileElement::tertiaryColour_get() const + { + auto ctx = GetContext()->GetScriptEngine().GetContext(); + auto el = _element->AsWall(); + if (el != nullptr) + duk_push_int(ctx, el->GetTertiaryColour()); + else + duk_push_null(ctx); + return DukValue::take_from_stack(ctx); + } + void ScTileElement::tertiaryColour_set(uint8_t value) + { + ThrowIfGameStateNotMutable(); + auto el = _element->AsWall(); + if (el != nullptr) + { + el->SetTertiaryColour(value); + Invalidate(); + } + } + + DukValue ScTileElement::bannerIndex_get() const + { + auto ctx = GetContext()->GetScriptEngine().GetContext(); + BannerIndex idx = _element->GetBannerIndex(); + if (idx == BANNER_INDEX_NULL) + duk_push_null(ctx); + else + duk_push_int(ctx, idx); + return DukValue::take_from_stack(ctx); + } + void ScTileElement::bannerIndex_set(uint16_t value) + { + ThrowIfGameStateNotMutable(); + switch (_element->GetType()) + { + case TILE_ELEMENT_TYPE_LARGE_SCENERY: + { + auto el = _element->AsLargeScenery(); + el->SetBannerIndex(value); + Invalidate(); + break; + } + case TILE_ELEMENT_TYPE_WALL: + { + auto el = _element->AsWall(); + el->SetBannerIndex(value); + Invalidate(); + break; + } + case TILE_ELEMENT_TYPE_BANNER: + { + auto el = _element->AsBanner(); + el->SetIndex(value); + Invalidate(); + break; + } + } + } + + // Deprecated in favor of seperate 'edges' and 'corners' properties, + // left here to maintain compatibility with older plugins. + /** @deprecated */ + uint8_t ScTileElement::edgesAndCorners_get() const + { + auto el = _element->AsPath(); + return el != nullptr ? el->GetEdgesAndCorners() : 0; + } + /** @deprecated */ + void ScTileElement::edgesAndCorners_set(uint8_t value) + { + ThrowIfGameStateNotMutable(); + auto el = _element->AsPath(); + if (el != nullptr) + { + el->SetEdgesAndCorners(value); + Invalidate(); + } + } + + DukValue ScTileElement::edges_get() const + { + auto ctx = GetContext()->GetScriptEngine().GetContext(); + auto el = _element->AsPath(); + if (el != nullptr) + duk_push_int(ctx, el->GetEdges()); + else + duk_push_null(ctx); + return DukValue::take_from_stack(ctx); + } + void ScTileElement::edges_set(uint8_t value) + { + ThrowIfGameStateNotMutable(); + auto el = _element->AsPath(); + if (el != nullptr) + { + el->SetEdges(value); + Invalidate(); + } + } + + DukValue ScTileElement::corners_get() const + { + auto ctx = GetContext()->GetScriptEngine().GetContext(); + auto el = _element->AsPath(); + if (el != nullptr) + duk_push_int(ctx, el->GetCorners()); + else + duk_push_null(ctx); + return DukValue::take_from_stack(ctx); + } + void ScTileElement::corners_set(uint8_t value) + { + ThrowIfGameStateNotMutable(); + auto el = _element->AsPath(); + if (el != nullptr) + { + el->SetCorners(value); + Invalidate(); + } + } + + DukValue ScTileElement::slopeDirection_get() const + { + auto ctx = GetContext()->GetScriptEngine().GetContext(); + auto el = _element->AsPath(); + if (el != nullptr && el->IsSloped()) + duk_push_int(ctx, el->GetSlopeDirection()); + else + duk_push_null(ctx); + return DukValue::take_from_stack(ctx); + } + void ScTileElement::slopeDirection_set(const DukValue& value) + { + ThrowIfGameStateNotMutable(); + auto el = _element->AsPath(); + if (el != nullptr) + { + if (value.type() == DukValue::Type::NUMBER) + { + el->SetSloped(true); + el->SetSlopeDirection(value.as_int()); + } + else + { + el->SetSloped(false); + el->SetSlopeDirection(0); + } + Invalidate(); + } + } + + DukValue ScTileElement::isQueue_get() const + { + auto ctx = GetContext()->GetScriptEngine().GetContext(); + auto el = _element->AsPath(); + if (el != nullptr) + duk_push_boolean(ctx, el->IsQueue()); + else + duk_push_null(ctx); + return DukValue::take_from_stack(ctx); + } + void ScTileElement::isQueue_set(bool value) + { + ThrowIfGameStateNotMutable(); + auto el = _element->AsPath(); + if (el != nullptr) + { + el->SetIsQueue(value); + Invalidate(); + } + } + + DukValue ScTileElement::queueBannerDirection_get() const + { + auto ctx = GetContext()->GetScriptEngine().GetContext(); + auto el = _element->AsPath(); + if (el != nullptr && el->HasQueueBanner()) + duk_push_int(ctx, el->GetQueueBannerDirection()); + else + duk_push_null(ctx); + return DukValue::take_from_stack(ctx); + } + void ScTileElement::queueBannerDirection_set(const DukValue& value) + { + ThrowIfGameStateNotMutable(); + auto el = _element->AsPath(); + if (el != nullptr) + { + if (value.type() == DukValue::Type::NUMBER) + { + el->SetHasQueueBanner(true); + el->SetQueueBannerDirection(value.as_int()); + } + else + { + el->SetHasQueueBanner(false); + el->SetQueueBannerDirection(0); + } + Invalidate(); + } + } + + DukValue ScTileElement::isBlockedByVehicle_get() const + { + auto ctx = GetContext()->GetScriptEngine().GetContext(); + auto el = _element->AsPath(); + if (el != nullptr) + duk_push_boolean(ctx, el->IsBlockedByVehicle()); + else + duk_push_null(ctx); + return DukValue::take_from_stack(ctx); + } + void ScTileElement::isBlockedByVehicle_set(bool value) + { + ThrowIfGameStateNotMutable(); + auto el = _element->AsPath(); + if (el != nullptr) + { + el->SetIsBlockedByVehicle(value); + Invalidate(); + } + } + + DukValue ScTileElement::isWide_get() const + { + auto ctx = GetContext()->GetScriptEngine().GetContext(); + auto el = _element->AsPath(); + if (el != nullptr) + duk_push_boolean(ctx, el->IsWide()); + else + duk_push_null(ctx); + return DukValue::take_from_stack(ctx); + } + void ScTileElement::isWide_set(bool value) + { + ThrowIfGameStateNotMutable(); + auto el = _element->AsPath(); + if (el != nullptr) + { + el->SetWide(value); + Invalidate(); + } + } + + DukValue ScTileElement::addition_get() const + { + auto ctx = GetContext()->GetScriptEngine().GetContext(); + auto el = _element->AsPath(); + if (el != nullptr && el->HasAddition()) + duk_push_int(ctx, el->GetAddition() - 1); + else + duk_push_null(ctx); + return DukValue::take_from_stack(ctx); + } + void ScTileElement::addition_set(const DukValue& value) + { + ThrowIfGameStateNotMutable(); + auto el = _element->AsPath(); + if (el != nullptr) + { + if (value.type() == DukValue::Type::NUMBER) + { + auto addition = value.as_int(); + if (addition >= 0 && addition <= 254) + { + el->SetAddition(addition + 1); + } + } + else + { + el->SetAddition(0); + } + Invalidate(); + } + } + + DukValue ScTileElement::additionStatus_get() const + { + auto ctx = GetContext()->GetScriptEngine().GetContext(); + auto el = _element->AsPath(); + if (el != nullptr && el->HasAddition()) + duk_push_int(ctx, el->GetAdditionStatus()); + else + duk_push_null(ctx); + return DukValue::take_from_stack(ctx); + } + void ScTileElement::additionStatus_set(uint8_t value) + { + ThrowIfGameStateNotMutable(); + auto el = _element->AsPath(); + if (el != nullptr) + if (el->HasAddition()) + { + el->SetAdditionStatus(value); + Invalidate(); + } + } + + DukValue ScTileElement::isAdditionBroken_get() const + { + auto ctx = GetContext()->GetScriptEngine().GetContext(); + auto el = _element->AsPath(); + if (el != nullptr && el->HasAddition()) + duk_push_boolean(ctx, el->IsBroken()); + else + duk_push_null(ctx); + return DukValue::take_from_stack(ctx); + } + void ScTileElement::isAdditionBroken_set(bool value) + { + ThrowIfGameStateNotMutable(); + auto el = _element->AsPath(); + if (el != nullptr) + { + el->SetIsBroken(value); + Invalidate(); + } + } + + DukValue ScTileElement::isAdditionGhost_get() const + { + auto ctx = GetContext()->GetScriptEngine().GetContext(); + auto el = _element->AsPath(); + if (el != nullptr && el->HasAddition()) + duk_push_boolean(ctx, el->AdditionIsGhost()); + else + duk_push_null(ctx); + return DukValue::take_from_stack(ctx); + } + void ScTileElement::isAdditionGhost_set(bool value) + { + ThrowIfGameStateNotMutable(); + auto el = _element->AsPath(); + if (el != nullptr) + { + el->SetAdditionIsGhost(value); + Invalidate(); + } + } + + DukValue ScTileElement::footpathObject_get() const + { + auto ctx = GetContext()->GetScriptEngine().GetContext(); + auto el = _element->AsEntrance(); + if (el != nullptr) + duk_push_int(ctx, el->GetPathType()); + else + duk_push_null(ctx); + return DukValue::take_from_stack(ctx); + } + void ScTileElement::footpathObject_set(uint8_t value) + { + ThrowIfGameStateNotMutable(); + auto el = _element->AsEntrance(); + if (el != nullptr) + { + el->SetPathType(value); + Invalidate(); + } + } + + DukValue ScTileElement::direction_get() const + { + auto ctx = GetContext()->GetScriptEngine().GetContext(); + switch (_element->GetType()) + { + case TILE_ELEMENT_TYPE_BANNER: + { + auto el = _element->AsBanner(); + duk_push_int(ctx, el->GetPosition()); + break; + } + case TILE_ELEMENT_TYPE_PATH: + case TILE_ELEMENT_TYPE_SURFACE: + { + duk_push_null(ctx); + break; + } + default: + { + duk_push_int(ctx, _element->GetDirection()); + break; + } + } + return DukValue::take_from_stack(ctx); + } + void ScTileElement::direction_set(uint8_t value) + { + ThrowIfGameStateNotMutable(); + switch (_element->GetType()) + { + case TILE_ELEMENT_TYPE_BANNER: + { + auto el = _element->AsBanner(); + el->SetPosition(value); + Invalidate(); + break; + } + case TILE_ELEMENT_TYPE_PATH: + case TILE_ELEMENT_TYPE_SURFACE: + { + break; + } + default: + { + _element->SetDirection(value); + Invalidate(); + } + } + } + + void ScTileElement::Invalidate() + { + map_invalidate_tile_full(_coords); + } + + void ScTileElement::Register(duk_context* ctx) + { + // All + dukglue_register_property(ctx, &ScTileElement::type_get, &ScTileElement::type_set, "type"); + dukglue_register_property(ctx, &ScTileElement::baseHeight_get, &ScTileElement::baseHeight_set, "baseHeight"); + dukglue_register_property(ctx, &ScTileElement::baseZ_get, &ScTileElement::baseZ_set, "baseZ"); + dukglue_register_property( + ctx, &ScTileElement::clearanceHeight_get, &ScTileElement::clearanceHeight_set, "clearanceHeight"); + dukglue_register_property(ctx, &ScTileElement::clearanceZ_get, &ScTileElement::clearanceZ_set, "clearanceZ"); + dukglue_register_property( + ctx, &ScTileElement::occupiedQuadrants_get, &ScTileElement::occupiedQuadrants_set, "occupiedQuadrants"); + dukglue_register_property(ctx, &ScTileElement::isGhost_get, &ScTileElement::isGhost_set, "isGhost"); + dukglue_register_property(ctx, &ScTileElement::isHidden_get, &ScTileElement::isHidden_set, "isHidden"); + + // 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 + dukglue_register_property(ctx, &ScTileElement::object_get, &ScTileElement::object_set, "object"); + + // Small Scenery | Wall | Large Scenery + dukglue_register_property(ctx, &ScTileElement::primaryColour_get, &ScTileElement::primaryColour_set, "primaryColour"); + dukglue_register_property( + ctx, &ScTileElement::secondaryColour_get, &ScTileElement::secondaryColour_set, "secondaryColour"); + + // Wall | Large Scenery | Banner + dukglue_register_property(ctx, &ScTileElement::bannerIndex_get, &ScTileElement::bannerIndex_set, "bannerIndex"); + + // Path | Track | Entrance + dukglue_register_property(ctx, &ScTileElement::ride_get, &ScTileElement::ride_set, "ride"); + dukglue_register_property(ctx, &ScTileElement::station_get, &ScTileElement::station_set, "station"); + + // Track | Entrance | Large Scenery + dukglue_register_property(ctx, &ScTileElement::sequence_get, &ScTileElement::sequence_set, "sequence"); + + // Surface | Wall + dukglue_register_property(ctx, &ScTileElement::slope_get, &ScTileElement::slope_set, "slope"); + + // Surface only + dukglue_register_property(ctx, &ScTileElement::waterHeight_get, &ScTileElement::waterHeight_set, "waterHeight"); + dukglue_register_property(ctx, &ScTileElement::surfaceStyle_get, &ScTileElement::surfaceStyle_set, "surfaceStyle"); + dukglue_register_property(ctx, &ScTileElement::edgeStyle_get, &ScTileElement::edgeStyle_set, "edgeStyle"); + dukglue_register_property(ctx, &ScTileElement::grassLength_get, &ScTileElement::grassLength_set, "grassLength"); + dukglue_register_property(ctx, &ScTileElement::hasOwnership_get, nullptr, "hasOwnership"); + dukglue_register_property(ctx, &ScTileElement::hasConstructionRights_get, nullptr, "hasConstructionRights"); + dukglue_register_property(ctx, &ScTileElement::ownership_get, &ScTileElement::ownership_set, "ownership"); + dukglue_register_property(ctx, &ScTileElement::parkFences_get, &ScTileElement::parkFences_set, "parkFences"); + + // Footpath only + dukglue_register_property( + ctx, &ScTileElement::edgesAndCorners_get, &ScTileElement::edgesAndCorners_set, "edgesAndCorners"); + dukglue_register_property(ctx, &ScTileElement::edges_get, &ScTileElement::edges_set, "edges"); + dukglue_register_property(ctx, &ScTileElement::corners_get, &ScTileElement::corners_set, "corners"); + dukglue_register_property( + ctx, &ScTileElement::slopeDirection_get, &ScTileElement::slopeDirection_set, "slopeDirection"); + dukglue_register_property(ctx, &ScTileElement::isQueue_get, &ScTileElement::isQueue_set, "isQueue"); + dukglue_register_property( + ctx, &ScTileElement::queueBannerDirection_get, &ScTileElement::queueBannerDirection_set, "queueBannerDirection"); + dukglue_register_property(ctx, &ScTileElement::queueBannerDirection_get, &ScTileElement::edges_set, "test"); + + dukglue_register_property( + ctx, &ScTileElement::isBlockedByVehicle_get, &ScTileElement::isBlockedByVehicle_set, "isBlockedByVehicle"); + dukglue_register_property(ctx, &ScTileElement::isWide_get, &ScTileElement::isWide_set, "isWide"); + + dukglue_register_property(ctx, &ScTileElement::addition_get, &ScTileElement::addition_set, "addition"); + dukglue_register_property( + ctx, &ScTileElement::additionStatus_get, &ScTileElement::additionStatus_set, "additionStatus"); + dukglue_register_property( + ctx, &ScTileElement::isAdditionBroken_get, &ScTileElement::isAdditionBroken_set, "isAdditionBroken"); + dukglue_register_property( + ctx, &ScTileElement::isAdditionGhost_get, &ScTileElement::isAdditionGhost_set, "isAdditionGhost"); + + // Track only + dukglue_register_property(ctx, &ScTileElement::trackType_get, &ScTileElement::trackType_set, "trackType"); + dukglue_register_property(ctx, &ScTileElement::mazeEntry_get, &ScTileElement::mazeEntry_set, "mazeEntry"); + dukglue_register_property(ctx, &ScTileElement::colourScheme_get, &ScTileElement::colourScheme_set, "colourScheme"); + dukglue_register_property(ctx, &ScTileElement::seatRotation_get, &ScTileElement::seatRotation_set, "seatRotation"); + dukglue_register_property( + ctx, &ScTileElement::brakeBoosterSpeed_get, &ScTileElement::brakeBoosterSpeed_set, "brakeBoosterSpeed"); + dukglue_register_property(ctx, &ScTileElement::hasChainLift_get, &ScTileElement::hasChainLift_set, "hasChainLift"); + dukglue_register_property(ctx, &ScTileElement::isInverted_get, &ScTileElement::isInverted_set, "isInverted"); + dukglue_register_property(ctx, &ScTileElement::hasCableLift_get, &ScTileElement::hasCableLift_set, "hasCableLift"); + + // Small Scenery only + dukglue_register_property(ctx, &ScTileElement::age_get, &ScTileElement::age_set, "age"); + dukglue_register_property(ctx, &ScTileElement::quadrant_get, &ScTileElement::quadrant_set, "quadrant"); + + // Wall only + dukglue_register_property( + ctx, &ScTileElement::tertiaryColour_get, &ScTileElement::tertiaryColour_set, "tertiaryColour"); + + // Entrance only + dukglue_register_property( + ctx, &ScTileElement::footpathObject_get, &ScTileElement::footpathObject_set, "footpathObject"); + } + +} // namespace OpenRCT2::Scripting + +#endif diff --git a/src/openrct2/scripting/bindings/world/ScTileElement.hpp b/src/openrct2/scripting/bindings/world/ScTileElement.hpp new file mode 100644 index 0000000000..9b0fcd7060 --- /dev/null +++ b/src/openrct2/scripting/bindings/world/ScTileElement.hpp @@ -0,0 +1,198 @@ +/***************************************************************************** + * Copyright (c) 2014-2021 OpenRCT2 developers + * + * For a complete list of all authors, please refer to contributors.md + * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 is licensed under the GNU General Public License version 3. + *****************************************************************************/ + +#pragma once + +#ifdef ENABLE_SCRIPTING + +# include "../../../Context.h" +# include "../../../common.h" +# include "../../../core/Guard.hpp" +# include "../../../ride/Track.h" +# include "../../../world/Footpath.h" +# include "../../../world/Scenery.h" +# include "../../../world/Sprite.h" +# include "../../../world/Surface.h" +# include "../../Duktape.hpp" +# include "../../ScriptEngine.h" + +# include +# include +# include + +namespace OpenRCT2::Scripting +{ + class ScTileElement + { + protected: + CoordsXY _coords; + TileElement* _element; + + public: + ScTileElement(const CoordsXY& coords, TileElement* element); + + private: + std::string type_get() const; + void type_set(std::string value); + + uint8_t baseHeight_get() const; + void baseHeight_set(uint8_t newBaseHeight); + + uint16_t baseZ_get() const; + void baseZ_set(uint16_t value); + + uint8_t clearanceHeight_get() const; + void clearanceHeight_set(uint8_t newClearanceHeight); + + uint16_t clearanceZ_get() const; + void clearanceZ_set(uint16_t value); + + DukValue slope_get() const; + void slope_set(uint8_t value); + + DukValue waterHeight_get() const; + void waterHeight_set(int32_t value); + + DukValue surfaceStyle_get() const; + void surfaceStyle_set(uint32_t value); + + DukValue edgeStyle_get() const; + void edgeStyle_set(uint32_t value); + + DukValue grassLength_get() const; + void grassLength_set(uint8_t value); + + DukValue hasOwnership_get() const; + + DukValue hasConstructionRights_get(); + + DukValue ownership_get() const; + void ownership_set(uint8_t value); + + DukValue parkFences_get() const; + void parkFences_set(uint8_t value); + + DukValue trackType_get() const; + void trackType_set(uint8_t value); + + DukValue sequence_get() const; + void sequence_set(uint8_t value); + + DukValue ride_get() const; + void ride_set(ride_id_t value); + + DukValue station_get() const; + void station_set(uint8_t value); + + DukValue hasChainLift_get() const; + void hasChainLift_set(bool value); + + DukValue mazeEntry_get() const; + void mazeEntry_set(uint16_t value); + + DukValue colourScheme_get() const; + void colourScheme_set(uint8_t value); + + DukValue seatRotation_get() const; + void seatRotation_set(uint8_t value); + + DukValue brakeBoosterSpeed_get() const; + void brakeBoosterSpeed_set(uint8_t value); + + DukValue isInverted_get() const; + void isInverted_set(bool value); + + DukValue hasCableLift_get() const; + void hasCableLift_set(bool value); + + DukValue object_get() const; + void object_set(uint32_t value); + + bool isHidden_get() const; + void isHidden_set(bool hide); + + DukValue age_get() const; + void age_set(uint8_t value); + + DukValue quadrant_get() const; + void quadrant_set(uint8_t value); + + uint8_t occupiedQuadrants_get() const; + void occupiedQuadrants_set(uint8_t value); + + bool isGhost_get() const; + void isGhost_set(bool value); + + DukValue primaryColour_get() const; + void primaryColour_set(uint8_t value); + + DukValue secondaryColour_get() const; + void secondaryColour_set(uint8_t value); + + DukValue tertiaryColour_get() const; + void tertiaryColour_set(uint8_t value); + + DukValue bannerIndex_get() const; + void bannerIndex_set(uint16_t value); + + // Deprecated in favor of seperate 'edges' and 'corners' properties, + // left here to maintain compatibility with older plugins. + /** @deprecated */ + uint8_t edgesAndCorners_get() const; + /** @deprecated */ + void edgesAndCorners_set(uint8_t value); + + DukValue edges_get() const; + void edges_set(uint8_t value); + + DukValue corners_get() const; + void corners_set(uint8_t value); + + DukValue slopeDirection_get() const; + void slopeDirection_set(const DukValue& value); + + DukValue isQueue_get() const; + void isQueue_set(bool value); + + DukValue queueBannerDirection_get() const; + void queueBannerDirection_set(const DukValue& value); + + DukValue isBlockedByVehicle_get() const; + void isBlockedByVehicle_set(bool value); + + DukValue isWide_get() const; + void isWide_set(bool value); + + DukValue addition_get() const; + void addition_set(const DukValue& value); + + DukValue additionStatus_get() const; + void additionStatus_set(uint8_t value); + + DukValue isAdditionBroken_get() const; + void isAdditionBroken_set(bool value); + + DukValue isAdditionGhost_get() const; + void isAdditionGhost_set(bool value); + + DukValue footpathObject_get() const; + void footpathObject_set(uint8_t value); + + DukValue direction_get() const; + void direction_set(uint8_t value); + + void Invalidate(); + + public: + static void Register(duk_context* ctx); + }; + +} // namespace OpenRCT2::Scripting + +#endif