/***************************************************************************** * 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"; default: return "unknown"; } } void ScTileElement::type_set(std::string value) { if (value == "surface") _element->type = TILE_ELEMENT_TYPE_SURFACE; else if (value == "footpath") _element->type = TILE_ELEMENT_TYPE_PATH; else if (value == "track") _element->type = TILE_ELEMENT_TYPE_TRACK; else if (value == "small_scenery") _element->type = TILE_ELEMENT_TYPE_SMALL_SCENERY; else if (value == "entrance") _element->type = TILE_ELEMENT_TYPE_ENTRANCE; else if (value == "wall") _element->type = TILE_ELEMENT_TYPE_WALL; else if (value == "large_scenery") _element->type = TILE_ELEMENT_TYPE_LARGE_SCENERY; else if (value == "banner") _element->type = TILE_ELEMENT_TYPE_BANNER; else { std::puts("Element type not recognised!"); return; } 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, EnumValue(el->GetRideIndex())); else duk_push_null(ctx); break; } case TILE_ELEMENT_TYPE_TRACK: { auto el = _element->AsTrack(); duk_push_int(ctx, EnumValue(el->GetRideIndex())); break; } case TILE_ELEMENT_TYPE_ENTRANCE: { auto el = _element->AsEntrance(); duk_push_int(ctx, EnumValue(el->GetRideIndex())); break; } default: { duk_push_null(ctx); break; } } return DukValue::take_from_stack(ctx); } void ScTileElement::ride_set(int32_t value) { ThrowIfGameStateNotMutable(); switch (_element->GetType()) { case TILE_ELEMENT_TYPE_PATH: { auto el = _element->AsPath(); if (!el->HasAddition()) { el->SetRideIndex(static_cast(value)); Invalidate(); } break; } case TILE_ELEMENT_TYPE_TRACK: { auto el = _element->AsTrack(); el->SetRideIndex(static_cast(value)); Invalidate(); break; } case TILE_ELEMENT_TYPE_ENTRANCE: { auto el = _element->AsEntrance(); el->SetRideIndex(static_cast(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->GetLegacyPathEntryIndex()); 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(const DukValue& value) { ThrowIfGameStateNotMutable(); auto index = FromDuk(value); switch (_element->GetType()) { case TILE_ELEMENT_TYPE_PATH: { auto el = _element->AsPath(); el->SetLegacyPathEntryIndex(index); Invalidate(); break; } case TILE_ELEMENT_TYPE_SMALL_SCENERY: { auto el = _element->AsSmallScenery(); el->SetEntryIndex(index); Invalidate(); break; } case TILE_ELEMENT_TYPE_LARGE_SCENERY: { auto el = _element->AsLargeScenery(); el->SetEntryIndex(index); Invalidate(); break; } case TILE_ELEMENT_TYPE_WALL: { auto el = _element->AsWall(); el->SetEntryIndex(index); Invalidate(); break; } case TILE_ELEMENT_TYPE_ENTRANCE: { auto el = _element->AsEntrance(); el->SetEntranceType(index); Invalidate(); break; } } } bool ScTileElement::isHidden_get() const { return _element->IsInvisible(); } void ScTileElement::isHidden_set(bool hide) { ThrowIfGameStateNotMutable(); _element->SetInvisible(hide); 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::surfaceObject_get() const { auto ctx = GetContext()->GetScriptEngine().GetContext(); if (_element->GetType() == TILE_ELEMENT_TYPE_PATH) { auto el = _element->AsPath(); auto index = el->GetSurfaceEntryIndex(); if (index != OBJECT_ENTRY_INDEX_NULL) { duk_push_int(ctx, index); } else { duk_push_null(ctx); } } else { duk_push_null(ctx); } return DukValue::take_from_stack(ctx); } void ScTileElement::surfaceObject_set(const DukValue& value) { ThrowIfGameStateNotMutable(); if (_element->GetType() == TILE_ELEMENT_TYPE_PATH) { auto el = _element->AsPath(); el->SetSurfaceEntryIndex(FromDuk(value)); Invalidate(); } } DukValue ScTileElement::railingsObject_get() const { auto ctx = GetContext()->GetScriptEngine().GetContext(); if (_element->GetType() == TILE_ELEMENT_TYPE_PATH) { auto el = _element->AsPath(); auto index = el->GetRailingsEntryIndex(); if (index != OBJECT_ENTRY_INDEX_NULL) { duk_push_int(ctx, index); } else { duk_push_null(ctx); } } else { duk_push_null(ctx); } return DukValue::take_from_stack(ctx); } void ScTileElement::railingsObject_set(const DukValue& value) { ThrowIfGameStateNotMutable(); if (_element->GetType() == TILE_ELEMENT_TYPE_PATH) { auto el = _element->AsPath(); el->SetRailingsEntryIndex(FromDuk(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) { auto index = el->GetLegacyPathEntryIndex(); if (index != OBJECT_ENTRY_INDEX_NULL) { duk_push_int(ctx, index); } else { duk_push_null(ctx); } } else { duk_push_null(ctx); } return DukValue::take_from_stack(ctx); } void ScTileElement::footpathObject_set(const DukValue& value) { ThrowIfGameStateNotMutable(); auto el = _element->AsEntrance(); if (el != nullptr) { el->SetLegacyPathEntryIndex(FromDuk(value)); Invalidate(); } } DukValue ScTileElement::footpathSurfaceObject_get() const { auto ctx = GetContext()->GetScriptEngine().GetContext(); auto el = _element->AsEntrance(); if (el != nullptr) { auto index = el->GetSurfaceEntryIndex(); if (index != OBJECT_ENTRY_INDEX_NULL) { duk_push_int(ctx, index); } else { duk_push_null(ctx); } } else { duk_push_null(ctx); } return DukValue::take_from_stack(ctx); } void ScTileElement::footpathSurfaceObject_set(const DukValue& value) { ThrowIfGameStateNotMutable(); auto el = _element->AsEntrance(); if (el != nullptr) { el->SetSurfaceEntryIndex(FromDuk(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::isBlockedByVehicle_get, &ScTileElement::isBlockedByVehicle_set, "isBlockedByVehicle"); dukglue_register_property(ctx, &ScTileElement::isWide_get, &ScTileElement::isWide_set, "isWide"); dukglue_register_property(ctx, &ScTileElement::surfaceObject_get, &ScTileElement::surfaceObject_set, "surfaceObject"); dukglue_register_property( ctx, &ScTileElement::railingsObject_get, &ScTileElement::railingsObject_set, "railingsObject"); 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"); dukglue_register_property( ctx, &ScTileElement::footpathSurfaceObject_get, &ScTileElement::footpathSurfaceObject_set, "footpathSurfaceObject"); } } // namespace OpenRCT2::Scripting #endif