From 2729956cef830a34bdf760d6879cff863d5c108e Mon Sep 17 00:00:00 2001 From: Ted John Date: Mon, 17 Apr 2023 22:35:09 +0100 Subject: [PATCH] Add scenery group object interface --- distribution/openrct2.d.ts | 34 +++++++ src/openrct2/object/SceneryGroupObject.cpp | 5 + src/openrct2/object/SceneryGroupObject.h | 1 + src/openrct2/scripting/ScriptEngine.cpp | 1 + .../scripting/bindings/game/ScContext.hpp | 2 + .../scripting/bindings/object/ScObject.hpp | 95 ++++++++++++++++++- 6 files changed, 137 insertions(+), 1 deletion(-) diff --git a/distribution/openrct2.d.ts b/distribution/openrct2.d.ts index fd02debea6..b7415c2f80 100644 --- a/distribution/openrct2.d.ts +++ b/distribution/openrct2.d.ts @@ -1777,6 +1777,40 @@ declare global { readonly removalPrice: number; } + /** + * Represents the object definition of a scenery group. + */ + interface SceneryGroupObject extends LoadedImageObject { + /** + * The scenery items that belong to this scenery group. + */ + readonly items: SceneryGroupObjectItem[]; + } + + interface SceneryGroupObjectItem { + /** + * The JSON identifier of the object. + * Undefined if object only has a legacy identifier. + */ + identifier?: string; + + /** + * The DAT identifier of the object. + * Undefined if object only has a JSON identifier. + */ + legacyIdentifier?: string; + + /** + * The type of object + */ + type: ObjectType; + + /** + * The object index + */ + object: number | null; + } + /** * Represents a ride or stall within the park. */ diff --git a/src/openrct2/object/SceneryGroupObject.cpp b/src/openrct2/object/SceneryGroupObject.cpp index 7a6d32ca66..3eb485a4bf 100644 --- a/src/openrct2/object/SceneryGroupObject.cpp +++ b/src/openrct2/object/SceneryGroupObject.cpp @@ -243,3 +243,8 @@ uint16_t SceneryGroupObject::GetNumIncludedObjects() const { return static_cast(_items.size()); } + +const std::vector& SceneryGroupObject::GetItems() const +{ + return _items; +} diff --git a/src/openrct2/object/SceneryGroupObject.h b/src/openrct2/object/SceneryGroupObject.h index 9f1307889c..6c95bbb2a8 100644 --- a/src/openrct2/object/SceneryGroupObject.h +++ b/src/openrct2/object/SceneryGroupObject.h @@ -41,6 +41,7 @@ public: void SetRepositoryItem(ObjectRepositoryItem* item) const override; uint16_t GetNumIncludedObjects() const; + const std::vector& GetItems() const; private: static std::vector ReadItems(OpenRCT2::IStream* stream); diff --git a/src/openrct2/scripting/ScriptEngine.cpp b/src/openrct2/scripting/ScriptEngine.cpp index 8d9f9172a0..4893325724 100644 --- a/src/openrct2/scripting/ScriptEngine.cpp +++ b/src/openrct2/scripting/ScriptEngine.cpp @@ -405,6 +405,7 @@ void ScriptEngine::Initialise() ScNetwork::Register(ctx); ScObject::Register(ctx); ScSmallSceneryObject::Register(ctx); + ScSceneryGroupObject::Register(ctx); ScPark::Register(ctx); ScParkMessage::Register(ctx); ScPlayer::Register(ctx); diff --git a/src/openrct2/scripting/bindings/game/ScContext.hpp b/src/openrct2/scripting/bindings/game/ScContext.hpp index 73a2009e5f..ffd2dc72c3 100644 --- a/src/openrct2/scripting/bindings/game/ScContext.hpp +++ b/src/openrct2/scripting/bindings/game/ScContext.hpp @@ -168,6 +168,8 @@ namespace OpenRCT2::Scripting return GetObjectAsDukValue(ctx, std::make_shared(type, index)); case ObjectType::SmallScenery: return GetObjectAsDukValue(ctx, std::make_shared(type, index)); + case ObjectType::SceneryGroup: + return GetObjectAsDukValue(ctx, std::make_shared(type, index)); default: return GetObjectAsDukValue(ctx, std::make_shared(type, index)); } diff --git a/src/openrct2/scripting/bindings/object/ScObject.hpp b/src/openrct2/scripting/bindings/object/ScObject.hpp index 9a51f7c2e5..a8978817da 100644 --- a/src/openrct2/scripting/bindings/object/ScObject.hpp +++ b/src/openrct2/scripting/bindings/object/ScObject.hpp @@ -15,6 +15,7 @@ # include "../../../common.h" # include "../../../object/ObjectManager.h" # include "../../../object/RideObject.h" +# include "../../../object/SceneryGroupObject.h" # include "../../../object/SmallSceneryObject.h" # include "../../Duktape.hpp" # include "../../ScriptEngine.h" @@ -58,7 +59,7 @@ namespace OpenRCT2::Scripting return static_cast(i); } } - return ObjectType::None; + return std::nullopt; } static std::string_view ObjectTypeToString(uint8_t type) @@ -865,6 +866,98 @@ namespace OpenRCT2::Scripting return static_cast(ScObject::GetObject()); } }; + + class ScSceneryGroupObject : public ScObject + { + public: + ScSceneryGroupObject(ObjectType type, int32_t index) + : ScObject(type, index) + { + } + + static void Register(duk_context* ctx) + { + dukglue_set_base_class(ctx); + dukglue_register_property(ctx, &ScSceneryGroupObject::items_get, nullptr, "items"); + } + + private: + DukValue items_get() const + { + auto* gameContext = GetContext(); + auto* ctx = gameContext->GetScriptEngine().GetContext(); + + duk_push_array(ctx); + + auto obj = GetObject(); + if (obj != nullptr) + { + auto& objManager = gameContext->GetObjectManager(); + + duk_uarridx_t index = 0; + auto& items = obj->GetItems(); + for (const auto& item : items) + { + auto objectIndex = objManager.GetLoadedObjectEntryIndex(item); + auto object = objManager.GetLoadedObject(item); + + DukObject dukObj(ctx); + if (item.Generation == ObjectGeneration::JSON) + { + dukObj.Set("identifier", item.Identifier); + if (object != nullptr) + { + auto legacyIdentifier = object->GetLegacyIdentifier(); + if (!legacyIdentifier.empty()) + { + dukObj.Set("legacyIdentifier", legacyIdentifier); + } + } + } + else + { + dukObj.Set("legacyIdentifier", item.Entry.GetName()); + if (object != nullptr) + { + auto identifier = object->GetIdentifier(); + if (!identifier.empty()) + { + dukObj.Set("identifier", identifier); + } + } + } + if (object != nullptr) + { + dukObj.Set("type", ObjectTypeToString(EnumValue(object->GetObjectType()))); + } + else + { + dukObj.Set("type", ObjectTypeToString(EnumValue(item.Type))); + } + if (objectIndex == OBJECT_ENTRY_INDEX_NULL) + { + dukObj.Set("object", nullptr); + } + else + { + dukObj.Set("object", objectIndex); + } + + dukObj.Take().push(); + duk_put_prop_index(ctx, -2, index); + index++; + } + } + + return DukValue::take_from_stack(ctx, -1); + } + + protected: + SceneryGroupObject* GetObject() const + { + return static_cast(ScObject::GetObject()); + } + }; } // namespace OpenRCT2::Scripting #endif