Implement other scenery objects

This commit is contained in:
Ted John 2023-04-17 23:46:15 +01:00
parent 2729956cef
commit 1a73a0be68
4 changed files with 240 additions and 89 deletions

View File

@ -225,6 +225,10 @@ declare global {
getObject(type: "music", index: number): LoadedObject;
getObject(type: "ride", index: number): RideObject;
getObject(type: "small_scenery", index: number): SmallSceneryObject;
getObject(type: "large_scenery", index: number): LargeSceneryObject;
getObject(type: "wall", index: number): WallSceneryObject;
getObject(type: "footpath_addition", index: number): FootpathAdditionSceneryObject;
getObject(type: "banner", index: number): BannerSceneryObject;
getAllObjects(type: ObjectType): LoadedImageObject[];
getAllObjects(type: "music"): LoadedObject[];
@ -1752,10 +1756,46 @@ declare global {
readonly numVerticalFramesOverride: number;
}
interface SceneryObject extends LoadedImageObject {
/**
* A list of scenery groups this object belongs to. This may not contain any
* scenery groups that contain this object by default. This is typically
* used for custom objects to be part of existing scenery groups.
*/
readonly sceneryGroups: ObjectReference[];
}
/**
* Represents a reference to an object which may or may not be loaded.
*/
interface ObjectReference {
/**
* 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 the object definition of a small scenery item such a tree.
*/
interface SmallSceneryObject extends LoadedImageObject {
interface SmallSceneryObject extends SceneryObject {
/**
* Raw bit flags that describe characteristics of the scenery item.
*/
@ -1777,6 +1817,22 @@ declare global {
readonly removalPrice: number;
}
interface LargeSceneryObject extends SceneryObject {
}
interface WallSceneryObject extends SceneryObject {
}
interface FootpathAdditionSceneryObject extends SceneryObject {
}
interface BannerSceneryObject extends SceneryObject {
}
/**
* Represents the object definition of a scenery group.
*/
@ -1784,31 +1840,7 @@ declare global {
/**
* 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;
readonly items: ObjectReference[];
}
/**

View File

@ -404,7 +404,12 @@ void ScriptEngine::Initialise()
ScMap::Register(ctx);
ScNetwork::Register(ctx);
ScObject::Register(ctx);
ScSceneryObject::Register(ctx);
ScSmallSceneryObject::Register(ctx);
ScLargeSceneryObject::Register(ctx);
ScWallSceneryObject::Register(ctx);
ScFootpathAdditionSceneryObject::Register(ctx);
ScBannerSceneryObject::Register(ctx);
ScSceneryGroupObject::Register(ctx);
ScPark::Register(ctx);
ScParkMessage::Register(ctx);

View File

@ -168,6 +168,14 @@ namespace OpenRCT2::Scripting
return GetObjectAsDukValue(ctx, std::make_shared<ScRideObject>(type, index));
case ObjectType::SmallScenery:
return GetObjectAsDukValue(ctx, std::make_shared<ScSmallSceneryObject>(type, index));
case ObjectType::LargeScenery:
return GetObjectAsDukValue(ctx, std::make_shared<ScLargeSceneryObject>(type, index));
case ObjectType::Walls:
return GetObjectAsDukValue(ctx, std::make_shared<ScWallSceneryObject>(type, index));
case ObjectType::PathBits:
return GetObjectAsDukValue(ctx, std::make_shared<ScFootpathAdditionSceneryObject>(type, index));
case ObjectType::Banners:
return GetObjectAsDukValue(ctx, std::make_shared<ScBannerSceneryObject>(type, index));
case ObjectType::SceneryGroup:
return GetObjectAsDukValue(ctx, std::make_shared<ScSceneryGroupObject>(type, index));
default:

View File

@ -792,17 +792,114 @@ namespace OpenRCT2::Scripting
}
};
class ScSmallSceneryObject : public ScObject
class ScSceneryObject : public ScObject
{
public:
ScSmallSceneryObject(ObjectType type, int32_t index)
ScSceneryObject(ObjectType type, int32_t index)
: ScObject(type, index)
{
}
static void Register(duk_context* ctx)
{
dukglue_set_base_class<ScObject, ScSmallSceneryObject>(ctx);
dukglue_set_base_class<ScObject, ScSceneryObject>(ctx);
dukglue_register_property(ctx, &ScSceneryObject::sceneryGroups_get, nullptr, "sceneryGroups");
}
private:
DukValue sceneryGroups_get() const
{
auto* gameContext = GetContext();
auto* ctx = gameContext->GetScriptEngine().GetContext();
duk_push_array(ctx);
auto obj = GetObject();
if (obj != nullptr)
{
auto& scgDescriptor = obj->GetPrimarySceneryGroup();
if (scgDescriptor.HasValue())
{
auto dukScg = CreateObjectMetaReference(scgDescriptor);
dukScg.push();
duk_put_prop_index(ctx, -2, 0);
}
}
return DukValue::take_from_stack(ctx, -1);
}
SceneryObject* GetObject() const
{
return static_cast<SceneryObject*>(ScObject::GetObject());
}
public:
static DukValue CreateObjectMetaReference(const ObjectEntryDescriptor& descriptor)
{
auto* gameContext = GetContext();
auto* ctx = gameContext->GetScriptEngine().GetContext();
auto& objManager = gameContext->GetObjectManager();
auto objectIndex = objManager.GetLoadedObjectEntryIndex(descriptor);
auto object = objManager.GetLoadedObject(descriptor);
DukObject dukObj(ctx);
if (descriptor.Generation == ObjectGeneration::JSON)
{
dukObj.Set("identifier", descriptor.Identifier);
if (object != nullptr)
{
auto legacyIdentifier = object->GetLegacyIdentifier();
if (!legacyIdentifier.empty())
{
dukObj.Set("legacyIdentifier", legacyIdentifier);
}
}
}
else
{
dukObj.Set("legacyIdentifier", descriptor.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(descriptor.Type)));
}
if (objectIndex == OBJECT_ENTRY_INDEX_NULL)
{
dukObj.Set("object", nullptr);
}
else
{
dukObj.Set("object", objectIndex);
}
return dukObj.Take();
}
};
class ScSmallSceneryObject : public ScSceneryObject
{
public:
ScSmallSceneryObject(ObjectType type, int32_t index)
: ScSceneryObject(type, index)
{
}
static void Register(duk_context* ctx)
{
dukglue_set_base_class<ScSceneryObject, ScSmallSceneryObject>(ctx);
dukglue_register_property(ctx, &ScSmallSceneryObject::flags_get, nullptr, "flags");
dukglue_register_property(ctx, &ScSmallSceneryObject::height_get, nullptr, "height");
dukglue_register_property(ctx, &ScSmallSceneryObject::price_get, nullptr, "price");
@ -820,16 +917,6 @@ namespace OpenRCT2::Scripting
return 0;
}
uint8_t height_get() const
{
auto sceneryEntry = GetLegacyData();
if (sceneryEntry != nullptr)
{
return sceneryEntry->height;
}
return 0;
}
uint8_t price_get() const
{
auto sceneryEntry = GetLegacyData();
@ -840,6 +927,16 @@ namespace OpenRCT2::Scripting
return 0;
}
uint8_t height_get() const
{
auto sceneryEntry = GetLegacyData();
if (sceneryEntry != nullptr)
{
return sceneryEntry->height;
}
return 0;
}
uint8_t removalPrice_get() const
{
auto sceneryEntry = GetLegacyData();
@ -867,6 +964,62 @@ namespace OpenRCT2::Scripting
}
};
class ScLargeSceneryObject : public ScSceneryObject
{
public:
ScLargeSceneryObject(ObjectType type, int32_t index)
: ScSceneryObject(type, index)
{
}
static void Register(duk_context* ctx)
{
dukglue_set_base_class<ScSceneryObject, ScLargeSceneryObject>(ctx);
}
};
class ScWallSceneryObject : public ScSceneryObject
{
public:
ScWallSceneryObject(ObjectType type, int32_t index)
: ScSceneryObject(type, index)
{
}
static void Register(duk_context* ctx)
{
dukglue_set_base_class<ScSceneryObject, ScWallSceneryObject>(ctx);
}
};
class ScFootpathAdditionSceneryObject : public ScSceneryObject
{
public:
ScFootpathAdditionSceneryObject(ObjectType type, int32_t index)
: ScSceneryObject(type, index)
{
}
static void Register(duk_context* ctx)
{
dukglue_set_base_class<ScSceneryObject, ScFootpathAdditionSceneryObject>(ctx);
}
};
class ScBannerSceneryObject : public ScSceneryObject
{
public:
ScBannerSceneryObject(ObjectType type, int32_t index)
: ScSceneryObject(type, index)
{
}
static void Register(duk_context* ctx)
{
dukglue_set_base_class<ScSceneryObject, ScBannerSceneryObject>(ctx);
}
};
class ScSceneryGroupObject : public ScObject
{
public:
@ -884,66 +1037,19 @@ namespace OpenRCT2::Scripting
private:
DukValue items_get() const
{
auto* gameContext = GetContext();
auto* ctx = gameContext->GetScriptEngine().GetContext();
auto* ctx = GetContext()->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();
auto dukItem = ScSceneryObject::CreateObjectMetaReference(item);
dukItem.push();
duk_put_prop_index(ctx, -2, index);
index++;
}