diff --git a/distribution/openrct2.d.ts b/distribution/openrct2.d.ts index e5f4938404..498e5fc30a 100644 --- a/distribution/openrct2.d.ts +++ b/distribution/openrct2.d.ts @@ -112,6 +112,17 @@ declare global { */ sharedStorage: Configuration; + /** + * Gets the loaded object at the given index. + * @param type The object type. + * @param index The index. + */ + getObject(type: ObjectType, index: number): Object; + getObject(type: "ride", index: number): RideObject; + + getAllObjects(type: ObjectType): Object[]; + getAllObjects(type: "ride"): RideObject[]; + /** * Gets a random integer within the specified range using the game's pseudo- * random number generator. This is part of the game state and shared across @@ -175,6 +186,22 @@ declare global { has(key: string): boolean; } + type ObjectType = + "ride" | + "small_scenery" | + "large_scenery" | + "wall" | + "banner" | + "footpath" | + "footpath_addition" | + "scenery_group" | + "park_entrance" | + "water" | + "terrain_surface" | + "terrain_edge" | + "station" | + "music"; + type HookType = "interval.tick" | "interval.day" | "network.chat" | "network.action" | "network.join" | "network.leave"; @@ -407,6 +434,16 @@ declare global { * Represents the definition of a loaded object (.DAT or .json) such a ride type or scenery item. */ interface Object { + /** + * The object type. + */ + readonly type: ObjectType; + + /** + * The index of the loaded object for the object type. + */ + readonly index: number; + /** * The unique name identifier of the object, e.g. "BURGB ". * This may have trailing spaces if the name is shorter than 8 characters. diff --git a/src/openrct2/scripting/ScContext.hpp b/src/openrct2/scripting/ScContext.hpp index bae9ed2e53..bed9c62764 100644 --- a/src/openrct2/scripting/ScContext.hpp +++ b/src/openrct2/scripting/ScContext.hpp @@ -14,11 +14,13 @@ # include "../actions/CustomAction.hpp" # include "../actions/ParkSetNameAction.hpp" # include "../actions/SmallSceneryPlaceAction.hpp" +# include "../object/ObjectManager.h" # include "../scenario/Scenario.h" # include "Duktape.hpp" # include "HookEngine.h" # include "ScConfiguration.hpp" # include "ScDisposable.hpp" +# include "ScObject.hpp" # include "ScriptEngine.h" # include @@ -51,8 +53,64 @@ namespace OpenRCT2::Scripting return std::make_shared(scriptEngine.GetSharedStorage()); } - void registerIntent(const DukValue& desc) + static DukValue CreateScObject(duk_context* ctx, uint8_t type, int32_t index) { + switch (type) + { + case OBJECT_TYPE_RIDE: + return GetObjectAsDukValue(ctx, std::make_shared(type, index)); + break; + default: + return GetObjectAsDukValue(ctx, std::make_shared(type, index)); + break; + } + } + + DukValue getObject(const std::string& typez, int32_t index) + { + auto ctx = GetContext()->GetScriptEngine().GetContext(); + auto& objManager = GetContext()->GetObjectManager(); + + auto type = ScObject::StringToObjectType(typez); + if (type) + { + auto obj = objManager.GetLoadedObject(*type, index); + if (obj != nullptr) + { + return CreateScObject(ctx, *type, index); + } + } + else + { + duk_error(ctx, DUK_ERR_ERROR, "Invalid object type."); + } + return {}; + } + + std::vector getAllObjects(const std::string& typez) + { + auto ctx = GetContext()->GetScriptEngine().GetContext(); + auto& objManager = GetContext()->GetObjectManager(); + + std::vector result; + auto type = ScObject::StringToObjectType(typez); + if (type) + { + auto count = object_entry_group_counts[*type]; + for (int32_t i = 0; i < count; i++) + { + auto obj = objManager.GetLoadedObject(*type, i); + if (obj != nullptr) + { + result.push_back(CreateScObject(ctx, *type, i)); + } + } + } + else + { + duk_error(ctx, DUK_ERR_ERROR, "Invalid object type."); + } + return result; } int32_t getRandom(int32_t min, int32_t max) @@ -230,8 +288,9 @@ namespace OpenRCT2::Scripting { dukglue_register_property(ctx, &ScContext::configuration_get, nullptr, "configuration"); dukglue_register_property(ctx, &ScContext::sharedStorage_get, nullptr, "sharedStorage"); + dukglue_register_method(ctx, &ScContext::getObject, "getObject"); + dukglue_register_method(ctx, &ScContext::getAllObjects, "getAllObjects"); dukglue_register_method(ctx, &ScContext::getRandom, "getRandom"); - dukglue_register_method(ctx, &ScContext::registerIntent, "registerIntent"); dukglue_register_method(ctx, &ScContext::subscribe, "subscribe"); dukglue_register_method(ctx, &ScContext::queryAction, "queryAction"); dukglue_register_method(ctx, &ScContext::executeAction, "executeAction"); diff --git a/src/openrct2/scripting/ScObject.hpp b/src/openrct2/scripting/ScObject.hpp new file mode 100644 index 0000000000..ee59e0f303 --- /dev/null +++ b/src/openrct2/scripting/ScObject.hpp @@ -0,0 +1,151 @@ +/***************************************************************************** + * Copyright (c) 2020 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 "../common.h" +# include "../object/ObjectManager.h" +# include "../object/RideObject.h" +# include "Duktape.hpp" +# include "ScriptEngine.h" + +# include + +namespace OpenRCT2::Scripting +{ + class ScObject + { + private: + uint8_t _type{}; + int32_t _index{}; + + public: + ScObject(uint8_t type, int32_t index) + : _type(type) + , _index(index) + { + } + + static void Register(duk_context* ctx) + { + dukglue_register_property(ctx, &ScObject::type_get, nullptr, "type"); + dukglue_register_property(ctx, &ScObject::index_get, nullptr, "index"); + dukglue_register_property(ctx, &ScObject::identifier_get, nullptr, "identifier"); + dukglue_register_property(ctx, &ScObject::name_get, nullptr, "name"); + } + + static std::optional StringToObjectType(const std::string_view& type) + { + for (uint8_t i = 0; i < OBJECT_TYPE_COUNT; i++) + { + auto s = ObjectTypeToString(i); + if (s == type) + { + return i; + } + } + return std::nullopt; + } + + static std::string_view ObjectTypeToString(uint8_t type) + { + static const char* Types[] = { "ride", "small_scenery", "large_scenery", "wall", "banner", + "footpath", "footpath_addition", "scenery_group", "park_entrance", "water", + "stex", "terrain_surface", "terrain_edge", "station", "music" }; + if (type >= std::size(Types)) + return "unknown"; + return Types[type]; + } + + private: + std::string type_get() + { + return std::string(ObjectTypeToString(_type)); + } + + int32_t index_get() + { + return _index; + } + + std::string identifier_get() + { + auto obj = GetObject(); + if (obj != nullptr) + { + return obj->GetIdentifier(); + } + return {}; + } + + std::string name_get() + { + auto obj = GetObject(); + if (obj != nullptr) + { + return obj->GetName(); + } + return {}; + } + + protected: + Object* GetObject() + { + auto& objManager = GetContext()->GetObjectManager(); + return objManager.GetLoadedObject(_type, _index); + } + }; + + class ScRideObject : public ScObject + { + public: + ScRideObject(uint8_t type, int32_t index) + : ScObject(type, index) + { + } + + static void Register(duk_context* ctx) + { + dukglue_set_base_class(ctx); + dukglue_register_property(ctx, &ScRideObject::description_get, nullptr, "description"); + dukglue_register_property(ctx, &ScRideObject::capacity_get, nullptr, "capacity"); + } + + private: + std::string description_get() + { + auto obj = GetObject(); + if (obj != nullptr) + { + return obj->GetDescription(); + } + return {}; + } + + std::string capacity_get() + { + auto obj = GetObject(); + if (obj != nullptr) + { + return obj->GetCapacity(); + } + return {}; + } + + protected: + RideObject* GetObject() + { + return static_cast(ScObject::GetObject()); + } + }; +} // namespace OpenRCT2::Scripting + +#endif diff --git a/src/openrct2/scripting/ScRide.hpp b/src/openrct2/scripting/ScRide.hpp index c5d1d83b0b..eb46929ef3 100644 --- a/src/openrct2/scripting/ScRide.hpp +++ b/src/openrct2/scripting/ScRide.hpp @@ -12,74 +12,13 @@ #ifdef __ENABLE_SCRIPTING__ # include "../common.h" -# include "../object/RideObject.h" # include "../ride/Ride.h" # include "Duktape.hpp" +# include "ScObject.hpp" # include "ScriptEngine.h" namespace OpenRCT2::Scripting { - class ScRideObject - { - private: - rct_ride_entry* _entry{}; - - public: - ScRideObject(rct_ride_entry* entry) - : _entry(entry) - { - } - - static void Register(duk_context* ctx) - { - dukglue_register_property(ctx, &ScRideObject::id_get, nullptr, "identifier"); - dukglue_register_property(ctx, &ScRideObject::name_get, nullptr, "name"); - dukglue_register_property(ctx, &ScRideObject::description_get, nullptr, "description"); - dukglue_register_property(ctx, &ScRideObject::capacity_get, nullptr, "capacity"); - } - - private: - std::string id_get() - { - auto obj = static_cast(_entry->obj); - if (obj != nullptr) - { - return obj->GetIdentifier(); - } - return {}; - } - - std::string name_get() - { - auto obj = static_cast(_entry->obj); - if (obj != nullptr) - { - return obj->GetName(); - } - return {}; - } - - std::string description_get() - { - auto obj = static_cast(_entry->obj); - if (obj != nullptr) - { - return obj->GetDescription(); - } - return {}; - } - - std::string capacity_get() - { - auto obj = static_cast(_entry->obj); - if (obj != nullptr) - { - return obj->GetCapacity(); - } - return {}; - } - }; - class ScRide { private: @@ -102,10 +41,10 @@ namespace OpenRCT2::Scripting auto ride = GetRide(); if (ride != nullptr) { - auto rideEntry = ride->GetRideEntry(); - if (rideEntry != nullptr) + auto rideObject = GetContext()->GetObjectManager().GetLoadedObject(OBJECT_TYPE_RIDE, ride->subtype); + if (rideObject != nullptr) { - return std::make_shared(rideEntry); + return std::make_shared(OBJECT_TYPE_RIDE, ride->subtype); } } return nullptr; diff --git a/src/openrct2/scripting/ScriptEngine.cpp b/src/openrct2/scripting/ScriptEngine.cpp index af4b9d5968..f1b324bde5 100644 --- a/src/openrct2/scripting/ScriptEngine.cpp +++ b/src/openrct2/scripting/ScriptEngine.cpp @@ -27,6 +27,7 @@ # include "ScDisposable.hpp" # include "ScMap.hpp" # include "ScNetwork.hpp" +# include "ScObject.hpp" # include "ScPark.hpp" # include "ScRide.hpp" # include "ScThing.hpp" @@ -373,6 +374,7 @@ void ScriptEngine::Initialise() ScDisposable::Register(ctx); ScMap::Register(ctx); ScNetwork::Register(ctx); + ScObject::Register(ctx); ScPark::Register(ctx); ScPlayer::Register(ctx); ScPlayerGroup::Register(ctx);