From a1f360ab7d822158a9140700d042c1a5a3479ca1 Mon Sep 17 00:00:00 2001 From: Ted John Date: Mon, 4 Dec 2017 21:56:06 +0000 Subject: [PATCH 01/93] Spike 1: Add RCT1 toilets JSON --- src/openrct2/object/ImageTable.cpp | 13 +++++++ src/openrct2/object/ImageTable.h | 1 + src/openrct2/object/Object.h | 2 + src/openrct2/object/ObjectFactory.cpp | 39 +++++++++++++++++++ src/openrct2/object/ObjectFactory.h | 2 + src/openrct2/object/ObjectRepository.cpp | 48 +++++++++++++++++------- src/openrct2/object/RideObject.cpp | 21 +++++++++++ src/openrct2/object/RideObject.h | 1 + 8 files changed, 114 insertions(+), 13 deletions(-) diff --git a/src/openrct2/object/ImageTable.cpp b/src/openrct2/object/ImageTable.cpp index d80bf172ae..17a25ff01c 100644 --- a/src/openrct2/object/ImageTable.cpp +++ b/src/openrct2/object/ImageTable.cpp @@ -97,3 +97,16 @@ void ImageTable::Read(IReadObjectContext * context, IStream * stream) throw; } } + +void ImageTable::AddImage(const rct_g1_element * g1, size_t length) +{ + auto dstOffset = _dataSize; + _dataSize += length; + _data = Memory::Reallocate(_data, _dataSize); + auto dst = (uint8 *)((size_t)_data + dstOffset); + Memory::Copy(dst, g1->offset, length); + + rct_g1_element newg1 = *g1; + newg1.offset = dst; + _entries.push_back(newg1); +} diff --git a/src/openrct2/object/ImageTable.h b/src/openrct2/object/ImageTable.h index 9edfa20391..080533d91b 100644 --- a/src/openrct2/object/ImageTable.h +++ b/src/openrct2/object/ImageTable.h @@ -37,4 +37,5 @@ public: void Read(IReadObjectContext * context, IStream * stream); const rct_g1_element * GetImages() const { return _entries.data(); } uint32 GetCount() const { return (uint32)_entries.size(); } + void AddImage(const rct_g1_element * g1, size_t length); }; diff --git a/src/openrct2/object/Object.h b/src/openrct2/object/Object.h index aa361cdf33..c02c2c95a0 100644 --- a/src/openrct2/object/Object.h +++ b/src/openrct2/object/Object.h @@ -17,6 +17,7 @@ #pragma once #include "../common.h" +#include "../core/Json.hpp" #include "ImageTable.h" #include "StringTable.h" @@ -168,6 +169,7 @@ public: const rct_object_entry * GetObjectEntry() const { return &_objectEntry; } virtual void * GetLegacyData() abstract; + virtual void ReadJson(IReadObjectContext * context, const json_t * root) { } virtual void ReadLegacy(IReadObjectContext * context, IStream * stream) abstract; virtual void Load() abstract; virtual void Unload() abstract; diff --git a/src/openrct2/object/ObjectFactory.cpp b/src/openrct2/object/ObjectFactory.cpp index 163be81b37..fd3fbc3466 100644 --- a/src/openrct2/object/ObjectFactory.cpp +++ b/src/openrct2/object/ObjectFactory.cpp @@ -16,6 +16,7 @@ #include "../core/Console.hpp" #include "../core/FileStream.hpp" +#include "../core/Json.hpp" #include "../core/Memory.hpp" #include "../core/MemoryStream.h" #include "../core/String.hpp" @@ -203,4 +204,42 @@ namespace ObjectFactory } return result; } + + Object * CreateObjectFromJsonFile(const std::string &path) + { + log_verbose("CreateObjectFromJsonFile(\"%s\")", path.c_str()); + + Object * result = nullptr; + try + { + auto jRoot = Json::ReadFromFile(path.c_str()); + auto jObjectType = json_object_get(jRoot, "objectType"); + if (json_is_string(jObjectType)) + { + auto objectType = std::string(json_string_value(jObjectType)); + if (objectType == "ride") + { + std::string objectName = "#RCT1TOI"; + rct_object_entry entry = { 0 }; + memcpy(entry.name, objectName.c_str(), 8); + result = new RideObject(entry); + auto readContext = ReadObjectContext(objectName.c_str()); + result->ReadJson(&readContext, jRoot); + if (readContext.WasError()) + { + throw Exception("Object has errors"); + } + } + } + json_decref(jRoot); + } + catch (Exception) + { + Console::Error::WriteLine("Unable to open or read '%s'", path); + + delete result; + result = nullptr; + } + return result; + } } diff --git a/src/openrct2/object/ObjectFactory.h b/src/openrct2/object/ObjectFactory.h index c8b1793f1d..e6173ff61d 100644 --- a/src/openrct2/object/ObjectFactory.h +++ b/src/openrct2/object/ObjectFactory.h @@ -25,4 +25,6 @@ namespace ObjectFactory Object * CreateObjectFromLegacyFile(const utf8 * path); Object * CreateObjectFromLegacyData(const rct_object_entry * entry, const void * data, size_t dataSize); Object * CreateObject(const rct_object_entry &entry); + + Object * CreateObjectFromJsonFile(const std::string &path); } diff --git a/src/openrct2/object/ObjectRepository.cpp b/src/openrct2/object/ObjectRepository.cpp index 0b423d38ac..94b4fd37d3 100644 --- a/src/openrct2/object/ObjectRepository.cpp +++ b/src/openrct2/object/ObjectRepository.cpp @@ -80,7 +80,7 @@ class ObjectFileIndex final : public FileIndex private: static constexpr uint32 MAGIC_NUMBER = 0x5844494F; // OIDX static constexpr uint16 VERSION = 17; - static constexpr auto PATTERN = "*.dat;*.pob"; + static constexpr auto PATTERN = "*.dat;*.pob;*.json"; public: explicit ObjectFileIndex(IPlatformEnvironment * env) : @@ -98,21 +98,36 @@ public: public: std::tuple Create(const std::string &path) const override { - auto object = ObjectFactory::CreateObjectFromLegacyFile(path.c_str()); - if (object != nullptr) + auto extension = Path::GetExtension(path); + if (String::Equals(extension, ".json", true)) { - ObjectRepositoryItem item = { 0 }; - item.ObjectEntry = *object->GetObjectEntry(); - item.Path = String::Duplicate(path); - item.Name = String::Duplicate(object->GetName()); - object->SetRepositoryItem(&item); - delete object; - return std::make_tuple(true, item); + auto object = ObjectFactory::CreateObjectFromJsonFile(path); + if (object != nullptr) + { + ObjectRepositoryItem item = { 0 }; + item.ObjectEntry = *object->GetObjectEntry(); + item.Path = String::Duplicate(path); + item.Name = String::Duplicate(object->GetName()); + object->SetRepositoryItem(&item); + delete object; + return std::make_tuple(true, item); + } } else { - return std::make_tuple(false, ObjectRepositoryItem()); + auto object = ObjectFactory::CreateObjectFromLegacyFile(path.c_str()); + if (object != nullptr) + { + ObjectRepositoryItem item = { 0 }; + item.ObjectEntry = *object->GetObjectEntry(); + item.Path = String::Duplicate(path); + item.Name = String::Duplicate(object->GetName()); + object->SetRepositoryItem(&item); + delete object; + return std::make_tuple(true, item); + } } + return std::make_tuple(false, ObjectRepositoryItem()); } protected: @@ -260,8 +275,15 @@ public: { Guard::ArgumentNotNull(ori, GUARD_LINE); - Object * object = ObjectFactory::CreateObjectFromLegacyFile(ori->Path); - return object; + auto extension = Path::GetExtension(ori->Path); + if (String::Equals(extension, ".json", true)) + { + return ObjectFactory::CreateObjectFromJsonFile(ori->Path); + } + else + { + return ObjectFactory::CreateObjectFromLegacyFile(ori->Path); + } } void RegisterLoadedObject(const ObjectRepositoryItem * ori, Object * object) override diff --git a/src/openrct2/object/RideObject.cpp b/src/openrct2/object/RideObject.cpp index f194ce4ed9..840ea94f72 100644 --- a/src/openrct2/object/RideObject.cpp +++ b/src/openrct2/object/RideObject.cpp @@ -532,3 +532,24 @@ uint8 RideObject::CalculateNumHorizontalFrames(const rct_ride_entry_vehicle * ve return numHorizontalFrames; } + +void RideObject::ReadJson(IReadObjectContext * context, const json_t * root) +{ + printf("RideObject::ReadJson(context, root)\n"); + _legacyType.ride_type[0] = RIDE_TYPE_TOILETS; + _legacyType.category[0] = RIDE_CATEGORY_SHOP; + + auto stringTable = GetStringTable(); + stringTable->SetString(0, 0, "RCT1 toilets"); + stringTable->SetString(1, 0, "Desc"); + stringTable->SetString(2, 0, "Capacity"); + stringTable->SetString(3, 0, "Vehicle"); + + auto imageTable = GetImageTable(); + auto g1 = *(gfx_get_g1_element(0x60000 + 64231)); + // auto g12 = gfx_get_g1_element(0x60000 + 64322); + // imageTable->AddImage(g1, (size_t)(g12->offset - g1->offset)); + g1.x_offset = 0; + g1.y_offset = 0; + imageTable->AddImage(&g1, 0x4000); +} diff --git a/src/openrct2/object/RideObject.h b/src/openrct2/object/RideObject.h index 27c467667f..b84f586838 100644 --- a/src/openrct2/object/RideObject.h +++ b/src/openrct2/object/RideObject.h @@ -34,6 +34,7 @@ public: void * GetLegacyData() override { return &_legacyType; } + void ReadJson(IReadObjectContext * context, const json_t * root) override; void ReadLegacy(IReadObjectContext * context, IStream * stream) override; void Load() override; void Unload() override; From 9ab0164b6f8f6a6a24a8b4e28910beefd94f09b7 Mon Sep 17 00:00:00 2001 From: Michael Steenbeek Date: Tue, 5 Dec 2017 13:35:39 +0100 Subject: [PATCH 02/93] Fix compiling and loading on macOS, load description --- src/openrct2/object/ObjectFactory.cpp | 2 +- src/openrct2/object/RideObject.cpp | 22 +++++++++++++++------- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/openrct2/object/ObjectFactory.cpp b/src/openrct2/object/ObjectFactory.cpp index fd3fbc3466..6039d01fc1 100644 --- a/src/openrct2/object/ObjectFactory.cpp +++ b/src/openrct2/object/ObjectFactory.cpp @@ -235,7 +235,7 @@ namespace ObjectFactory } catch (Exception) { - Console::Error::WriteLine("Unable to open or read '%s'", path); + Console::Error::WriteLine("Unable to open or read '%s'", path.c_str()); delete result; result = nullptr; diff --git a/src/openrct2/object/RideObject.cpp b/src/openrct2/object/RideObject.cpp index 840ea94f72..5cf2c6271c 100644 --- a/src/openrct2/object/RideObject.cpp +++ b/src/openrct2/object/RideObject.cpp @@ -540,16 +540,24 @@ void RideObject::ReadJson(IReadObjectContext * context, const json_t * root) _legacyType.category[0] = RIDE_CATEGORY_SHOP; auto stringTable = GetStringTable(); + auto jsonStrings = json_object_get(root, "strings"); + auto jsonDescription = json_object_get(jsonStrings, "description"); + auto enDescription = json_object_get(jsonDescription, "en-GB"); + stringTable->SetString(0, 0, "RCT1 toilets"); - stringTable->SetString(1, 0, "Desc"); + stringTable->SetString(1, 0, String::Duplicate(json_string_value(enDescription))); stringTable->SetString(2, 0, "Capacity"); stringTable->SetString(3, 0, "Vehicle"); auto imageTable = GetImageTable(); - auto g1 = *(gfx_get_g1_element(0x60000 + 64231)); - // auto g12 = gfx_get_g1_element(0x60000 + 64322); - // imageTable->AddImage(g1, (size_t)(g12->offset - g1->offset)); - g1.x_offset = 0; - g1.y_offset = 0; - imageTable->AddImage(&g1, 0x4000); + + if (is_csg_loaded()) + { + auto g1 = *(gfx_get_g1_element(0x60000 + 64231)); + // auto g12 = gfx_get_g1_element(0x60000 + 64322); + // imageTable->AddImage(g1, (size_t)(g12->offset - g1->offset)); + g1.x_offset = 0; + g1.y_offset = 0; + imageTable->AddImage(&g1, 0x4000); + } } From 3ffdfd1e5d2957384efe1b72beaa8f7635dcce70 Mon Sep 17 00:00:00 2001 From: Michael Steenbeek Date: Tue, 5 Dec 2017 14:09:10 +0100 Subject: [PATCH 03/93] Draw the building --- src/openrct2/object/RideObject.cpp | 20 ++++++++++++++++---- src/openrct2/sprites.h | 7 +++++++ 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/src/openrct2/object/RideObject.cpp b/src/openrct2/object/RideObject.cpp index 5cf2c6271c..96146cdac1 100644 --- a/src/openrct2/object/RideObject.cpp +++ b/src/openrct2/object/RideObject.cpp @@ -27,6 +27,7 @@ #include "../rct2/RCT2.h" #include "../ride/Ride.h" #include "../ride/Track.h" +#include "../sprites.h" RideObject::~RideObject() { @@ -537,7 +538,11 @@ void RideObject::ReadJson(IReadObjectContext * context, const json_t * root) { printf("RideObject::ReadJson(context, root)\n"); _legacyType.ride_type[0] = RIDE_TYPE_TOILETS; + _legacyType.ride_type[1] = RIDE_TYPE_NULL; + _legacyType.ride_type[2] = RIDE_TYPE_NULL; _legacyType.category[0] = RIDE_CATEGORY_SHOP; + _legacyType.category[1] = RIDE_CATEGORY_SHOP; + _legacyType.flags |= RIDE_ENTRY_FLAG_SEPARATE_RIDE; auto stringTable = GetStringTable(); auto jsonStrings = json_object_get(root, "strings"); @@ -553,11 +558,18 @@ void RideObject::ReadJson(IReadObjectContext * context, const json_t * root) if (is_csg_loaded()) { - auto g1 = *(gfx_get_g1_element(0x60000 + 64231)); - // auto g12 = gfx_get_g1_element(0x60000 + 64322); - // imageTable->AddImage(g1, (size_t)(g12->offset - g1->offset)); + auto g1 = *(gfx_get_g1_element(SPR_CSG_RIDE_PREVIEW_TOILETS)); + //auto g12 = *(gfx_get_g1_element(SPR_CSG_RIDE_PREVIEW_TOILETS + 1)); g1.x_offset = 0; g1.y_offset = 0; - imageTable->AddImage(&g1, 0x4000); + + for (size_t i = 0; i < MAX_RIDE_TYPES_PER_RIDE_ENTRY; i++) + { + imageTable->AddImage(&g1, 0x4000); //(size_t)(g12.offset - g1.offset)); + } + + rct_ride_entry_vehicle * vehicle0 = &_legacyType.vehicles[0]; + vehicle0->flags |= VEHICLE_SPRITE_FLAG_FLAT; + vehicle0->base_image_id = SPR_CSG_TOILETS_BEGIN; } } diff --git a/src/openrct2/sprites.h b/src/openrct2/sprites.h index 462ff6799b..43789da688 100644 --- a/src/openrct2/sprites.h +++ b/src/openrct2/sprites.h @@ -17,6 +17,8 @@ #ifndef _SPRITES_H_ #define _SPRITES_H_ +#include + enum { SPR_NONE = -1, @@ -872,6 +874,11 @@ enum { SPR_CSG_WALL_TEXTURE_STONE_GREY = SPR_CSG_BEGIN + 47376, SPR_CSG_WALL_TEXTURE_SKYSCRAPER_A = SPR_CSG_BEGIN + 47377, SPR_CSG_WALL_TEXTURE_SKYSCRAPER_B = SPR_CSG_BEGIN + 47378, + + SPR_CSG_TOILETS_BEGIN = SPR_CSG_BEGIN + 61289, + + SPR_CSG_RIDE_PREVIEWS_BEGIN = SPR_CSG_BEGIN + 64195, + SPR_CSG_RIDE_PREVIEW_TOILETS = SPR_CSG_RIDE_PREVIEWS_BEGIN + RCT1_RIDE_TYPE_TOILETS, }; #endif From e3b202989fa5a011c332d301129b49a178e76b80 Mon Sep 17 00:00:00 2001 From: Michael Steenbeek Date: Tue, 5 Dec 2017 15:12:28 +0100 Subject: [PATCH 04/93] Read more from JSON, attempt at supporting more types of stalls --- src/openrct2/object/ObjectFactory.cpp | 13 ++++++++- src/openrct2/object/RideObject.cpp | 40 +++++++++++++++++++++------ src/openrct2/sprites.h | 1 + 3 files changed, 44 insertions(+), 10 deletions(-) diff --git a/src/openrct2/object/ObjectFactory.cpp b/src/openrct2/object/ObjectFactory.cpp index 6039d01fc1..e3fe8b2c98 100644 --- a/src/openrct2/object/ObjectFactory.cpp +++ b/src/openrct2/object/ObjectFactory.cpp @@ -219,7 +219,18 @@ namespace ObjectFactory auto objectType = std::string(json_string_value(jObjectType)); if (objectType == "ride") { - std::string objectName = "#RCT1TOI"; + std::string objectName; + const char * id = json_string_value(json_object_get(jRoot, "id")); + + if (String::Equals(id, "rct1.icecr")) + { + objectName = "#RCT1ICE"; + } + else + { + objectName = "#RCT1TOI"; + } + rct_object_entry entry = { 0 }; memcpy(entry.name, objectName.c_str(), 8); result = new RideObject(entry); diff --git a/src/openrct2/object/RideObject.cpp b/src/openrct2/object/RideObject.cpp index 96146cdac1..26349ffcc3 100644 --- a/src/openrct2/object/RideObject.cpp +++ b/src/openrct2/object/RideObject.cpp @@ -537,20 +537,42 @@ uint8 RideObject::CalculateNumHorizontalFrames(const rct_ride_entry_vehicle * ve void RideObject::ReadJson(IReadObjectContext * context, const json_t * root) { printf("RideObject::ReadJson(context, root)\n"); - _legacyType.ride_type[0] = RIDE_TYPE_TOILETS; + const char * rideType = json_string_value(json_object_get(json_object_get(root, "properties"), "type")); + const char * category = json_string_value(json_object_get(json_object_get(root, "properties"), "category")); + sint32 previewImg = 0; + sint32 imageStart = 0; + + if (String::Equals(rideType, "restroom") || + String::Equals(rideType, "toilets")) // object tool should be fixed to generate toilets, not restroom. + { + _legacyType.ride_type[0] = RIDE_TYPE_TOILETS; + previewImg = SPR_CSG_RIDE_PREVIEW_TOILETS; + imageStart = SPR_CSG_TOILETS_BEGIN; + } + else if (String::Equals(rideType, "foodstall")) + { + _legacyType.ride_type[0] = RIDE_TYPE_FOOD_STALL; + previewImg = SPR_CSG_RIDE_PREVIEW_ICE_CREAM_STALL; + imageStart = 61281; + } _legacyType.ride_type[1] = RIDE_TYPE_NULL; _legacyType.ride_type[2] = RIDE_TYPE_NULL; - _legacyType.category[0] = RIDE_CATEGORY_SHOP; - _legacyType.category[1] = RIDE_CATEGORY_SHOP; + + if (String::Equals(rideType, "stall")) + { + _legacyType.category[0] = RIDE_CATEGORY_SHOP; + _legacyType.category[1] = RIDE_CATEGORY_SHOP; + } + _legacyType.flags |= RIDE_ENTRY_FLAG_SEPARATE_RIDE; auto stringTable = GetStringTable(); auto jsonStrings = json_object_get(root, "strings"); + auto jsonName = json_object_get(jsonStrings, "name"); auto jsonDescription = json_object_get(jsonStrings, "description"); - auto enDescription = json_object_get(jsonDescription, "en-GB"); - stringTable->SetString(0, 0, "RCT1 toilets"); - stringTable->SetString(1, 0, String::Duplicate(json_string_value(enDescription))); + stringTable->SetString(0, 0, json_string_value(json_object_get(jsonName, "en-GB"))); + stringTable->SetString(1, 0, json_string_value(json_object_get(jsonDescription, "en-GB"))); stringTable->SetString(2, 0, "Capacity"); stringTable->SetString(3, 0, "Vehicle"); @@ -558,8 +580,8 @@ void RideObject::ReadJson(IReadObjectContext * context, const json_t * root) if (is_csg_loaded()) { - auto g1 = *(gfx_get_g1_element(SPR_CSG_RIDE_PREVIEW_TOILETS)); - //auto g12 = *(gfx_get_g1_element(SPR_CSG_RIDE_PREVIEW_TOILETS + 1)); + auto g1 = *(gfx_get_g1_element(previewImg)); + //auto g12 = *(gfx_get_g1_element(previewImg + 1)); g1.x_offset = 0; g1.y_offset = 0; @@ -570,6 +592,6 @@ void RideObject::ReadJson(IReadObjectContext * context, const json_t * root) rct_ride_entry_vehicle * vehicle0 = &_legacyType.vehicles[0]; vehicle0->flags |= VEHICLE_SPRITE_FLAG_FLAT; - vehicle0->base_image_id = SPR_CSG_TOILETS_BEGIN; + vehicle0->base_image_id = imageStart; } } diff --git a/src/openrct2/sprites.h b/src/openrct2/sprites.h index 43789da688..a327515f8d 100644 --- a/src/openrct2/sprites.h +++ b/src/openrct2/sprites.h @@ -878,6 +878,7 @@ enum { SPR_CSG_TOILETS_BEGIN = SPR_CSG_BEGIN + 61289, SPR_CSG_RIDE_PREVIEWS_BEGIN = SPR_CSG_BEGIN + 64195, + SPR_CSG_RIDE_PREVIEW_ICE_CREAM_STALL = SPR_CSG_RIDE_PREVIEWS_BEGIN + RCT1_RIDE_TYPE_ICE_CREAM_STALL, SPR_CSG_RIDE_PREVIEW_TOILETS = SPR_CSG_RIDE_PREVIEWS_BEGIN + RCT1_RIDE_TYPE_TOILETS, }; From 7d3489a151b41b49e35dfe155ab1bf7e2e8122f8 Mon Sep 17 00:00:00 2001 From: Michael Steenbeek Date: Tue, 5 Dec 2017 15:39:31 +0100 Subject: [PATCH 05/93] Avoid toilets selling balloons --- src/openrct2/object/RideObject.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/openrct2/object/RideObject.cpp b/src/openrct2/object/RideObject.cpp index 26349ffcc3..d09d19ca4c 100644 --- a/src/openrct2/object/RideObject.cpp +++ b/src/openrct2/object/RideObject.cpp @@ -558,6 +558,9 @@ void RideObject::ReadJson(IReadObjectContext * context, const json_t * root) _legacyType.ride_type[1] = RIDE_TYPE_NULL; _legacyType.ride_type[2] = RIDE_TYPE_NULL; + _legacyType.shop_item = SHOP_ITEM_NONE; + _legacyType.shop_item_secondary = SHOP_ITEM_NONE; + if (String::Equals(rideType, "stall")) { _legacyType.category[0] = RIDE_CATEGORY_SHOP; From ad21e962eece4c85e5f842b1aad7714f14575d64 Mon Sep 17 00:00:00 2001 From: Michael Steenbeek Date: Tue, 5 Dec 2017 16:42:09 +0100 Subject: [PATCH 06/93] Allow import of RCT1 Ice Cream Stall --- src/openrct2/object/RideObject.cpp | 9 ++++++--- src/openrct2/ride/RideData.cpp | 4 ++-- src/openrct2/sprites.h | 1 + 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/openrct2/object/RideObject.cpp b/src/openrct2/object/RideObject.cpp index d09d19ca4c..5f604122e2 100644 --- a/src/openrct2/object/RideObject.cpp +++ b/src/openrct2/object/RideObject.cpp @@ -542,6 +542,9 @@ void RideObject::ReadJson(IReadObjectContext * context, const json_t * root) sint32 previewImg = 0; sint32 imageStart = 0; + _legacyType.shop_item = SHOP_ITEM_NONE; + _legacyType.shop_item_secondary = SHOP_ITEM_NONE; + if (String::Equals(rideType, "restroom") || String::Equals(rideType, "toilets")) // object tool should be fixed to generate toilets, not restroom. { @@ -553,13 +556,13 @@ void RideObject::ReadJson(IReadObjectContext * context, const json_t * root) { _legacyType.ride_type[0] = RIDE_TYPE_FOOD_STALL; previewImg = SPR_CSG_RIDE_PREVIEW_ICE_CREAM_STALL; - imageStart = 61281; + imageStart = SPR_CSG_ICE_CREAM_STALL_BEGIN; + _legacyType.shop_item = SHOP_ITEM_ICE_CREAM; } _legacyType.ride_type[1] = RIDE_TYPE_NULL; _legacyType.ride_type[2] = RIDE_TYPE_NULL; - _legacyType.shop_item = SHOP_ITEM_NONE; - _legacyType.shop_item_secondary = SHOP_ITEM_NONE; + if (String::Equals(rideType, "stall")) { diff --git a/src/openrct2/ride/RideData.cpp b/src/openrct2/ride/RideData.cpp index df604d8573..6305f9c05e 100644 --- a/src/openrct2/ride/RideData.cpp +++ b/src/openrct2/ride/RideData.cpp @@ -1538,7 +1538,7 @@ const uint32 ShopItemImage[SHOP_ITEM_COUNT] = { SPR_SHOP_ITEM_DRINK, SPR_SHOP_ITEM_BURGER, SPR_SHOP_ITEM_CHIPS, - SPR_SHOP_ITEM_ICE_CREAM, + SPR_CSG_ICE_CREAM_STALL_BEGIN + 3, SPR_SHOP_ITEM_CANDYFLOSS, SPR_SHOP_ITEM_EMPTY_CAN, SPR_SHOP_ITEM_RUBBISH, @@ -2092,7 +2092,7 @@ const rct_ride_properties RideProperties[RIDE_TYPE_COUNT] = { RIDE_TYPE_FLAG_HAS_LOAD_OPTIONS | RIDE_TYPE_FLAG_HAS_NO_TRACK | RIDE_TYPE_FLAG_16 | RIDE_TYPE_FLAG_TRACK_NO_WALLS | RIDE_TYPE_FLAG_FLAT_RIDE | RIDE_TYPE_FLAG_HAS_VEHICLE_COLOURS, 7, 15, 0, 0, 0, 0 }, // RIDE_TYPE_SWINGING_INVERTER_SHIP - {RIDE_TYPE_FLAG_3 | RIDE_TYPE_FLAG_CANNOT_HAVE_GAPS | RIDE_TYPE_FLAG_NO_TEST_MODE | RIDE_TYPE_FLAG_NO_VEHICLES | + {RIDE_TYPE_FLAG_HAS_TRACK_COLOUR_MAIN | RIDE_TYPE_FLAG_3 | RIDE_TYPE_FLAG_CANNOT_HAVE_GAPS | RIDE_TYPE_FLAG_NO_TEST_MODE | RIDE_TYPE_FLAG_NO_VEHICLES | RIDE_TYPE_FLAG_HAS_NO_TRACK | RIDE_TYPE_FLAG_IS_SHOP | RIDE_TYPE_FLAG_TRACK_NO_WALLS | RIDE_TYPE_FLAG_FLAT_RIDE | RIDE_TYPE_FLAG_SELLS_FOOD, 0, 0, 0, 0, 0, 0 }, // RIDE_TYPE_FOOD_STALL diff --git a/src/openrct2/sprites.h b/src/openrct2/sprites.h index a327515f8d..e0d1001b91 100644 --- a/src/openrct2/sprites.h +++ b/src/openrct2/sprites.h @@ -875,6 +875,7 @@ enum { SPR_CSG_WALL_TEXTURE_SKYSCRAPER_A = SPR_CSG_BEGIN + 47377, SPR_CSG_WALL_TEXTURE_SKYSCRAPER_B = SPR_CSG_BEGIN + 47378, + SPR_CSG_ICE_CREAM_STALL_BEGIN = SPR_CSG_BEGIN + 60625, SPR_CSG_TOILETS_BEGIN = SPR_CSG_BEGIN + 61289, SPR_CSG_RIDE_PREVIEWS_BEGIN = SPR_CSG_BEGIN + 64195, From 32d588d765a168550aa236c3a1db462d5235ed86 Mon Sep 17 00:00:00 2001 From: Ted John Date: Tue, 5 Dec 2017 18:57:14 +0000 Subject: [PATCH 07/93] Fix toilets image loading --- src/openrct2/drawing/Drawing.h | 1 + src/openrct2/drawing/Sprite.cpp | 22 ++++++++++++++++++++++ src/openrct2/object/ObjectFactory.cpp | 17 ++++------------- src/openrct2/object/RideObject.cpp | 26 ++++++++++++-------------- 4 files changed, 39 insertions(+), 27 deletions(-) diff --git a/src/openrct2/drawing/Drawing.h b/src/openrct2/drawing/Drawing.h index b240e59843..2346351e8d 100644 --- a/src/openrct2/drawing/Drawing.h +++ b/src/openrct2/drawing/Drawing.h @@ -339,6 +339,7 @@ void scrolling_text_initialise_bitmaps(); sint32 scrolling_text_setup(struct paint_session * session, rct_string_id stringId, uint16 scroll, uint16 scrollingMode); rct_size16 FASTCALL gfx_get_sprite_size(uint32 image_id); +size_t g1_calculate_data_size(const rct_g1_element * g1); void mask_scalar(sint32 width, sint32 height, const uint8 * RESTRICT maskSrc, const uint8 * RESTRICT colourSrc, uint8 * RESTRICT dst, sint32 maskWrap, sint32 colourWrap, sint32 dstWrap); diff --git a/src/openrct2/drawing/Sprite.cpp b/src/openrct2/drawing/Sprite.cpp index 0fc7f5c991..28cf83e38d 100644 --- a/src/openrct2/drawing/Sprite.cpp +++ b/src/openrct2/drawing/Sprite.cpp @@ -858,3 +858,25 @@ rct_size16 FASTCALL gfx_get_sprite_size(uint32 image_id) return size; } +size_t g1_calculate_data_size(const rct_g1_element * g1) +{ + if (g1->flags & G1_FLAG_RLE_COMPRESSION) + { + uint16 * offsets = (uint16 *)g1->offset; + uint8 * ptr = g1->offset + offsets[g1->height - 1]; + bool endOfLine = false; + do + { + uint8 chunk0 = *ptr++; + ptr++; // offset + uint8 chunkSize = chunk0 & 0x7F; + ptr += chunkSize; + endOfLine = (chunk0 & 0x80) != 0; + } while (!endOfLine); + return ptr - g1->offset; + } + else + { + return g1->width * g1->height; + } +} diff --git a/src/openrct2/object/ObjectFactory.cpp b/src/openrct2/object/ObjectFactory.cpp index e3fe8b2c98..b499f931e3 100644 --- a/src/openrct2/object/ObjectFactory.cpp +++ b/src/openrct2/object/ObjectFactory.cpp @@ -219,22 +219,13 @@ namespace ObjectFactory auto objectType = std::string(json_string_value(jObjectType)); if (objectType == "ride") { - std::string objectName; - const char * id = json_string_value(json_object_get(jRoot, "id")); - - if (String::Equals(id, "rct1.icecr")) - { - objectName = "#RCT1ICE"; - } - else - { - objectName = "#RCT1TOI"; - } + auto id = json_string_value(json_object_get(jRoot, "id")); + auto originalId = json_string_value(json_object_get(jRoot, "originalId")); rct_object_entry entry = { 0 }; - memcpy(entry.name, objectName.c_str(), 8); + memcpy(entry.name, originalId, 8); result = new RideObject(entry); - auto readContext = ReadObjectContext(objectName.c_str()); + auto readContext = ReadObjectContext(id); result->ReadJson(&readContext, jRoot); if (readContext.WasError()) { diff --git a/src/openrct2/object/RideObject.cpp b/src/openrct2/object/RideObject.cpp index 5f604122e2..b11419e840 100644 --- a/src/openrct2/object/RideObject.cpp +++ b/src/openrct2/object/RideObject.cpp @@ -537,8 +537,8 @@ uint8 RideObject::CalculateNumHorizontalFrames(const rct_ride_entry_vehicle * ve void RideObject::ReadJson(IReadObjectContext * context, const json_t * root) { printf("RideObject::ReadJson(context, root)\n"); - const char * rideType = json_string_value(json_object_get(json_object_get(root, "properties"), "type")); - const char * category = json_string_value(json_object_get(json_object_get(root, "properties"), "category")); + auto rideType = json_string_value(json_object_get(json_object_get(root, "properties"), "type")); + auto category = json_string_value(json_object_get(json_object_get(root, "properties"), "category")); sint32 previewImg = 0; sint32 imageStart = 0; @@ -562,9 +562,7 @@ void RideObject::ReadJson(IReadObjectContext * context, const json_t * root) _legacyType.ride_type[1] = RIDE_TYPE_NULL; _legacyType.ride_type[2] = RIDE_TYPE_NULL; - - - if (String::Equals(rideType, "stall")) + if (String::Equals(category, "stall")) { _legacyType.category[0] = RIDE_CATEGORY_SHOP; _legacyType.category[1] = RIDE_CATEGORY_SHOP; @@ -586,18 +584,18 @@ void RideObject::ReadJson(IReadObjectContext * context, const json_t * root) if (is_csg_loaded()) { - auto g1 = *(gfx_get_g1_element(previewImg)); - //auto g12 = *(gfx_get_g1_element(previewImg + 1)); - g1.x_offset = 0; - g1.y_offset = 0; - for (size_t i = 0; i < MAX_RIDE_TYPES_PER_RIDE_ENTRY; i++) { - imageTable->AddImage(&g1, 0x4000); //(size_t)(g12.offset - g1.offset)); + auto g1 = gfx_get_g1_element(previewImg); + imageTable->AddImage(g1, g1_calculate_data_size(g1)); + } + for (int i = 0; i < 6; i++) + { + auto g1 = gfx_get_g1_element(imageStart + i); + imageTable->AddImage(g1, g1_calculate_data_size(g1)); } - rct_ride_entry_vehicle * vehicle0 = &_legacyType.vehicles[0]; - vehicle0->flags |= VEHICLE_SPRITE_FLAG_FLAT; - vehicle0->base_image_id = imageStart; + vehicle0->sprite_flags |= VEHICLE_SPRITE_FLAG_FLAT; + vehicle0->base_image_id = 0; } } From f6fd79eca486c4ad361f9360603aab53c5697d59 Mon Sep 17 00:00:00 2001 From: Ted John Date: Tue, 5 Dec 2017 20:08:47 +0000 Subject: [PATCH 08/93] Move length calculation to ImageTable.cpp --- src/openrct2/drawing/Sprite.cpp | 5 ++++- src/openrct2/object/ImageTable.cpp | 3 ++- src/openrct2/object/ImageTable.h | 2 +- src/openrct2/object/RideObject.cpp | 4 ++-- 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/openrct2/drawing/Sprite.cpp b/src/openrct2/drawing/Sprite.cpp index 28cf83e38d..01a5c96078 100644 --- a/src/openrct2/drawing/Sprite.cpp +++ b/src/openrct2/drawing/Sprite.cpp @@ -379,7 +379,10 @@ bool gfx_load_csg() { _csg.elements[i].offset += (uintptr_t)_csg.data; // RCT1 used zoomed offsets that counted from the beginning of the file, rather than from the current sprite. - _csg.elements[i].zoomed_offset = i - (SPR_CSG_BEGIN + _csg.elements[i].zoomed_offset); + if (_csg.elements[i].zoomed_offset != 0) + { + _csg.elements[i].zoomed_offset = i - (SPR_CSG_BEGIN + _csg.elements[i].zoomed_offset); + } } _csgLoaded = true; return true; diff --git a/src/openrct2/object/ImageTable.cpp b/src/openrct2/object/ImageTable.cpp index 17a25ff01c..065cc643a0 100644 --- a/src/openrct2/object/ImageTable.cpp +++ b/src/openrct2/object/ImageTable.cpp @@ -98,8 +98,9 @@ void ImageTable::Read(IReadObjectContext * context, IStream * stream) } } -void ImageTable::AddImage(const rct_g1_element * g1, size_t length) +void ImageTable::AddImage(const rct_g1_element * g1) { + auto length = g1_calculate_data_size(g1); auto dstOffset = _dataSize; _dataSize += length; _data = Memory::Reallocate(_data, _dataSize); diff --git a/src/openrct2/object/ImageTable.h b/src/openrct2/object/ImageTable.h index 080533d91b..a30107ac97 100644 --- a/src/openrct2/object/ImageTable.h +++ b/src/openrct2/object/ImageTable.h @@ -37,5 +37,5 @@ public: void Read(IReadObjectContext * context, IStream * stream); const rct_g1_element * GetImages() const { return _entries.data(); } uint32 GetCount() const { return (uint32)_entries.size(); } - void AddImage(const rct_g1_element * g1, size_t length); + void AddImage(const rct_g1_element * g1); }; diff --git a/src/openrct2/object/RideObject.cpp b/src/openrct2/object/RideObject.cpp index b11419e840..d2f881fc0c 100644 --- a/src/openrct2/object/RideObject.cpp +++ b/src/openrct2/object/RideObject.cpp @@ -587,12 +587,12 @@ void RideObject::ReadJson(IReadObjectContext * context, const json_t * root) for (size_t i = 0; i < MAX_RIDE_TYPES_PER_RIDE_ENTRY; i++) { auto g1 = gfx_get_g1_element(previewImg); - imageTable->AddImage(g1, g1_calculate_data_size(g1)); + imageTable->AddImage(g1); } for (int i = 0; i < 6; i++) { auto g1 = gfx_get_g1_element(imageStart + i); - imageTable->AddImage(g1, g1_calculate_data_size(g1)); + imageTable->AddImage(g1); } rct_ride_entry_vehicle * vehicle0 = &_legacyType.vehicles[0]; vehicle0->sprite_flags |= VEHICLE_SPRITE_FLAG_FLAT; From bf7c3931e77a9b4510cd418912e4ff39e9b94159 Mon Sep 17 00:00:00 2001 From: Ted John Date: Tue, 5 Dec 2017 20:35:13 +0000 Subject: [PATCH 09/93] Parse images from JSON --- src/openrct2/drawing/Sprite.cpp | 22 ++++++ src/openrct2/object/ImageTable.cpp | 22 +++--- src/openrct2/object/RideObject.cpp | 105 +++++++++++++++++++++++------ 3 files changed, 122 insertions(+), 27 deletions(-) diff --git a/src/openrct2/drawing/Sprite.cpp b/src/openrct2/drawing/Sprite.cpp index 01a5c96078..9e7442ebbc 100644 --- a/src/openrct2/drawing/Sprite.cpp +++ b/src/openrct2/drawing/Sprite.cpp @@ -878,6 +878,28 @@ size_t g1_calculate_data_size(const rct_g1_element * g1) } while (!endOfLine); return ptr - g1->offset; } + else if (g1->flags & G1_FLAG_RLE_COMPRESSION) + { + if (g1->offset == nullptr) + { + return 0; + } + else + { + uint16 * offsets = (uint16 *)g1->offset; + uint8 * ptr = g1->offset + offsets[g1->height - 1]; + bool endOfLine = false; + do + { + uint8 chunk0 = *ptr++; + ptr++; // offset + uint8 chunkSize = chunk0 & 0x7F; + ptr += chunkSize; + endOfLine = (chunk0 & 0x80) != 0; + } while (!endOfLine); + return ptr - g1->offset; + } + } else { return g1->width * g1->height; diff --git a/src/openrct2/object/ImageTable.cpp b/src/openrct2/object/ImageTable.cpp index 065cc643a0..0cb48d0d56 100644 --- a/src/openrct2/object/ImageTable.cpp +++ b/src/openrct2/object/ImageTable.cpp @@ -100,14 +100,20 @@ void ImageTable::Read(IReadObjectContext * context, IStream * stream) void ImageTable::AddImage(const rct_g1_element * g1) { - auto length = g1_calculate_data_size(g1); - auto dstOffset = _dataSize; - _dataSize += length; - _data = Memory::Reallocate(_data, _dataSize); - auto dst = (uint8 *)((size_t)_data + dstOffset); - Memory::Copy(dst, g1->offset, length); - rct_g1_element newg1 = *g1; - newg1.offset = dst; + auto length = g1_calculate_data_size(g1); + if (length == 0) + { + newg1.offset = 0; + } + else + { + auto dstOffset = _dataSize; + _dataSize += length; + _data = Memory::Reallocate(_data, _dataSize); + auto dst = (uint8 *)((size_t)_data + dstOffset); + Memory::Copy(dst, g1->offset, length); + newg1.offset = dst; + } _entries.push_back(newg1); } diff --git a/src/openrct2/object/RideObject.cpp b/src/openrct2/object/RideObject.cpp index d2f881fc0c..18c4f4adbd 100644 --- a/src/openrct2/object/RideObject.cpp +++ b/src/openrct2/object/RideObject.cpp @@ -534,13 +534,87 @@ uint8 RideObject::CalculateNumHorizontalFrames(const rct_ride_entry_vehicle * ve return numHorizontalFrames; } +static std::vector ParseRange(std::string s) +{ + // Currently only supports [###] or [###..###] + std::vector result; + if (s.length() >= 3 && s[0] == '[' && s[s.length() - 1] == ']') + { + s = s.substr(1, s.length() - 2); + auto parts = String::Split(s, ".."); + if (parts.size() == 1) + { + result.push_back(std::stoi(parts[0])); + } + else + { + auto left = std::stoi(parts[0]); + auto right = std::stoi(parts[1]); + if (left <= right) + { + for (auto i = left; i <= right; i++) + { + result.push_back(i); + } + } + else + { + for (auto i = right; i >= left; i--) + { + result.push_back(i); + } + } + } + } + return result; +} + +static std::vector ParseImages(std::string s) +{ + std::vector result; + if (s.empty()) + { + rct_g1_element emptyg1 = { 0 }; + result.push_back(emptyg1); + } + else if (String::StartsWith(s, "$CSG")) + { + if (is_csg_loaded()) + { + auto range = ParseRange(s.substr(4)); + if (range.size() > 0) + { + for (auto i : range) + { + auto g1 = gfx_get_g1_element(SPR_CSG_BEGIN + i); + result.push_back(*g1); + } + } + } + } + return result; +} + +static std::vector GetJsonStringArray(const json_t * arr) +{ + std::vector result; + if (json_is_array(arr)) + { + auto count = json_array_size(arr); + for (size_t i = 0; i < count; i++) + { + auto element = json_string_value(json_array_get(arr, i)); + result.push_back(element); + } + } + return result; +} + void RideObject::ReadJson(IReadObjectContext * context, const json_t * root) { printf("RideObject::ReadJson(context, root)\n"); auto rideType = json_string_value(json_object_get(json_object_get(root, "properties"), "type")); auto category = json_string_value(json_object_get(json_object_get(root, "properties"), "category")); - sint32 previewImg = 0; - sint32 imageStart = 0; _legacyType.shop_item = SHOP_ITEM_NONE; _legacyType.shop_item_secondary = SHOP_ITEM_NONE; @@ -549,14 +623,10 @@ void RideObject::ReadJson(IReadObjectContext * context, const json_t * root) String::Equals(rideType, "toilets")) // object tool should be fixed to generate toilets, not restroom. { _legacyType.ride_type[0] = RIDE_TYPE_TOILETS; - previewImg = SPR_CSG_RIDE_PREVIEW_TOILETS; - imageStart = SPR_CSG_TOILETS_BEGIN; } else if (String::Equals(rideType, "foodstall")) { _legacyType.ride_type[0] = RIDE_TYPE_FOOD_STALL; - previewImg = SPR_CSG_RIDE_PREVIEW_ICE_CREAM_STALL; - imageStart = SPR_CSG_ICE_CREAM_STALL_BEGIN; _legacyType.shop_item = SHOP_ITEM_ICE_CREAM; } _legacyType.ride_type[1] = RIDE_TYPE_NULL; @@ -581,21 +651,18 @@ void RideObject::ReadJson(IReadObjectContext * context, const json_t * root) stringTable->SetString(3, 0, "Vehicle"); auto imageTable = GetImageTable(); - - if (is_csg_loaded()) + auto jsonImages = json_object_get(root, "images"); + auto imageElements = GetJsonStringArray(jsonImages); + for (const auto &ie : imageElements) { - for (size_t i = 0; i < MAX_RIDE_TYPES_PER_RIDE_ENTRY; i++) + auto images = ParseImages(ie); + for (const auto &g1 : images) { - auto g1 = gfx_get_g1_element(previewImg); - imageTable->AddImage(g1); + imageTable->AddImage(&g1); } - for (int i = 0; i < 6; i++) - { - auto g1 = gfx_get_g1_element(imageStart + i); - imageTable->AddImage(g1); - } - rct_ride_entry_vehicle * vehicle0 = &_legacyType.vehicles[0]; - vehicle0->sprite_flags |= VEHICLE_SPRITE_FLAG_FLAT; - vehicle0->base_image_id = 0; } + + rct_ride_entry_vehicle * vehicle0 = &_legacyType.vehicles[0]; + vehicle0->sprite_flags |= VEHICLE_SPRITE_FLAG_FLAT; + vehicle0->base_image_id = 0; } From 773ab868fe51c2906e31a089a31f16b3a195da1b Mon Sep 17 00:00:00 2001 From: Ted John Date: Wed, 6 Dec 2017 19:55:53 +0000 Subject: [PATCH 10/93] Parse new form of original id --- src/openrct2/object/ObjectFactory.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/openrct2/object/ObjectFactory.cpp b/src/openrct2/object/ObjectFactory.cpp index b499f931e3..7adac8c280 100644 --- a/src/openrct2/object/ObjectFactory.cpp +++ b/src/openrct2/object/ObjectFactory.cpp @@ -220,10 +220,19 @@ namespace ObjectFactory if (objectType == "ride") { auto id = json_string_value(json_object_get(jRoot, "id")); - auto originalId = json_string_value(json_object_get(jRoot, "originalId")); rct_object_entry entry = { 0 }; - memcpy(entry.name, originalId, 8); + auto originalId = String::ToStd(json_string_value(json_object_get(jRoot, "originalId"))); + auto originalName = originalId; + if (originalId.length() == 8 + 1 + 8 + 1 + 8) + { + entry.flags = std::stoul(originalId.substr(0, 8), 0, 16); + originalName = originalId.substr(9, 8); + entry.checksum = std::stoul(originalId.substr(18, 8), 0, 16); + } + auto minLength = std::min(8, originalName.length()); + memcpy(entry.name, originalName.c_str(), minLength); + result = new RideObject(entry); auto readContext = ReadObjectContext(id); result->ReadJson(&readContext, jRoot); From 5eba067abac772f75b869b532be52c4105214e78 Mon Sep 17 00:00:00 2001 From: Ted John Date: Wed, 6 Dec 2017 20:28:41 +0000 Subject: [PATCH 11/93] Load images from OBJDATA DATs --- src/openrct2/object/Object.h | 2 + src/openrct2/object/ObjectRepository.cpp | 4 +- src/openrct2/object/RideObject.cpp | 51 +++++++++++++++++++++++- 3 files changed, 53 insertions(+), 4 deletions(-) diff --git a/src/openrct2/object/Object.h b/src/openrct2/object/Object.h index c02c2c95a0..c00101254e 100644 --- a/src/openrct2/object/Object.h +++ b/src/openrct2/object/Object.h @@ -181,6 +181,8 @@ public: virtual void SetRepositoryItem(ObjectRepositoryItem * item) const { } + const ImageTable * GetImageTable() const { return &_imageTable; } + rct_object_entry GetScgWallsHeader(); rct_object_entry GetScgPathXHeader(); rct_object_entry CreateHeader(const char name[9], uint32 flags, uint32 checksum); diff --git a/src/openrct2/object/ObjectRepository.cpp b/src/openrct2/object/ObjectRepository.cpp index 94b4fd37d3..7b4387d672 100644 --- a/src/openrct2/object/ObjectRepository.cpp +++ b/src/openrct2/object/ObjectRepository.cpp @@ -90,8 +90,8 @@ public: env->GetFilePath(PATHID::CACHE_OBJECTS), std::string(PATTERN), std::vector({ - env->GetDirectoryPath(DIRBASE::RCT2, DIRID::OBJECT), - env->GetDirectoryPath(DIRBASE::USER, DIRID::OBJECT) })) + env->GetDirectoryPath(DIRBASE::USER, DIRID::OBJECT), + env->GetDirectoryPath(DIRBASE::RCT2, DIRID::OBJECT) })) { } diff --git a/src/openrct2/object/RideObject.cpp b/src/openrct2/object/RideObject.cpp index 18c4f4adbd..eb588cc498 100644 --- a/src/openrct2/object/RideObject.cpp +++ b/src/openrct2/object/RideObject.cpp @@ -569,6 +569,34 @@ static std::vector ParseRange(std::string s) return result; } +#include "../Context.h" +#include "../PlatformEnvironment.h" +#include "../core/Path.hpp" +#include "ObjectFactory.h" + +using namespace OpenRCT2; + +static std::vector LoadObjectImages(const std::string &name) +{ + std::vector result; + const auto env = GetContext()->GetPlatformEnvironment(); + auto objectsPath = env->GetDirectoryPath(DIRBASE::RCT2, DIRID::OBJECT); + auto objectPath = Path::Combine(objectsPath, name); + auto obj = ObjectFactory::CreateObjectFromLegacyFile(objectPath.c_str()); + auto imgTable = static_cast(obj)->GetImageTable(); + auto numImages = imgTable->GetCount(); + auto images = imgTable->GetImages(); + for (uint32 i = 0; i < numImages; i++) + { + auto g1 = images[i]; + auto length = g1_calculate_data_size(&g1); + g1.offset = Memory::Duplicate(g1.offset, length); + result.push_back(g1); + } + delete obj; + return result; +} + static std::vector ParseImages(std::string s) { std::vector result; @@ -586,12 +614,26 @@ static std::vector ParseImages(std::string s) { for (auto i : range) { - auto g1 = gfx_get_g1_element(SPR_CSG_BEGIN + i); - result.push_back(*g1); + auto g1 = *gfx_get_g1_element(SPR_CSG_BEGIN + i); + auto length = g1_calculate_data_size(&g1); + g1.offset = Memory::Duplicate(g1.offset, length); + result.push_back(g1); } } } } + else if (String::StartsWith(s, "$RCT2:OBJDATA/")) + { + auto name = s.substr(14); + auto rangeStart = name.find('['); + auto range = std::vector({ 0 }); + if (rangeStart != std::string::npos) + { + range = ParseRange(name.substr(rangeStart)); + name = name.substr(0, rangeStart); + } + return LoadObjectImages(name); + } return result; } @@ -607,6 +649,10 @@ static std::vector GetJsonStringArray(const json_t * arr) result.push_back(element); } } + else if (json_is_string(arr)) + { + result.push_back(json_string_value(arr)); + } return result; } @@ -659,6 +705,7 @@ void RideObject::ReadJson(IReadObjectContext * context, const json_t * root) for (const auto &g1 : images) { imageTable->AddImage(&g1); + Memory::Free(g1.offset); } } From ddd0df4a60176c21269b866afc2c7b04b71df22f Mon Sep 17 00:00:00 2001 From: Ted John Date: Thu, 7 Dec 2017 12:53:54 +0000 Subject: [PATCH 12/93] Parse ride type with lookup table --- src/openrct2/object/RideObject.cpp | 132 ++++++++++++++++++++++++----- 1 file changed, 113 insertions(+), 19 deletions(-) diff --git a/src/openrct2/object/RideObject.cpp b/src/openrct2/object/RideObject.cpp index eb588cc498..c389181fad 100644 --- a/src/openrct2/object/RideObject.cpp +++ b/src/openrct2/object/RideObject.cpp @@ -14,20 +14,31 @@ *****************************************************************************/ #pragma endregion +#include +#include +#include "../Context.h" #include "../core/IStream.hpp" #include "../core/Memory.hpp" +#include "../core/Path.hpp" #include "../core/String.hpp" #include "../OpenRCT2.h" #include "ObjectRepository.h" #include "RideObject.h" -#include "../ride/RideGroupManager.h" +#include "../ride/RideGroupManager.h" #include "../drawing/Drawing.h" #include "../localisation/Language.h" #include "../rct2/RCT2.h" #include "../ride/Ride.h" #include "../ride/Track.h" +#include "../OpenRCT2.h" +#include "../PlatformEnvironment.h" #include "../sprites.h" +#include "ObjectFactory.h" +#include "ObjectRepository.h" +#include "RideObject.h" + +using namespace OpenRCT2; RideObject::~RideObject() { @@ -569,13 +580,6 @@ static std::vector ParseRange(std::string s) return result; } -#include "../Context.h" -#include "../PlatformEnvironment.h" -#include "../core/Path.hpp" -#include "ObjectFactory.h" - -using namespace OpenRCT2; - static std::vector LoadObjectImages(const std::string &name) { std::vector result; @@ -656,28 +660,118 @@ static std::vector GetJsonStringArray(const json_t * arr) return result; } +static uint8 ParseRideType(const std::string &s) +{ + static const std::unordered_map LookupTable + { + { "spiral_rc", RIDE_TYPE_SPIRAL_ROLLER_COASTER }, + { "stand_up_rc", RIDE_TYPE_STAND_UP_ROLLER_COASTER }, + { "suspended_swinging_rc", RIDE_TYPE_SUSPENDED_SWINGING_COASTER }, + { "inverted_rc", RIDE_TYPE_INVERTED_ROLLER_COASTER }, + { "junior_rc", RIDE_TYPE_JUNIOR_ROLLER_COASTER }, + { "miniature_railway", RIDE_TYPE_MINIATURE_RAILWAY }, + { "monorail", RIDE_TYPE_MONORAIL }, + { "mini_suspended_rc", RIDE_TYPE_MINI_SUSPENDED_COASTER }, + { "boat_hire", RIDE_TYPE_BOAT_RIDE }, + { "wooden_wild_mouse", RIDE_TYPE_WOODEN_WILD_MOUSE }, + { "steeplechase", RIDE_TYPE_STEEPLECHASE }, + { "car_ride", RIDE_TYPE_CAR_RIDE }, + { "launched_freefall", RIDE_TYPE_LAUNCHED_FREEFALL }, + { "bobsleigh_rc", RIDE_TYPE_BOBSLEIGH_COASTER }, + { "observation_tower", RIDE_TYPE_OBSERVATION_TOWER }, + { "looping_rc", RIDE_TYPE_LOOPING_ROLLER_COASTER }, + { "dinghy_slide", RIDE_TYPE_DINGHY_SLIDE }, + { "mine_train_rc", RIDE_TYPE_MINE_TRAIN_COASTER }, + { "chairlift", RIDE_TYPE_CHAIRLIFT }, + { "corkscrew_rc", RIDE_TYPE_CORKSCREW_ROLLER_COASTER }, + { "maze", RIDE_TYPE_MAZE }, + { "spiral_slide", RIDE_TYPE_SPIRAL_SLIDE }, + { "go_karts", RIDE_TYPE_GO_KARTS }, + { "log_flume", RIDE_TYPE_LOG_FLUME }, + { "river_rapids", RIDE_TYPE_RIVER_RAPIDS }, + { "dodgems", RIDE_TYPE_DODGEMS }, + { "swinging_ship", RIDE_TYPE_SWINGING_SHIP }, + { "swinging_inverter_ship", RIDE_TYPE_SWINGING_INVERTER_SHIP }, + { "food_stall", RIDE_TYPE_FOOD_STALL }, + { "drink_stall", RIDE_TYPE_DRINK_STALL }, + { "shop", RIDE_TYPE_SHOP }, + { "merry_go_round", RIDE_TYPE_MERRY_GO_ROUND }, + { "information_kiosk", RIDE_TYPE_INFORMATION_KIOSK }, + { "toilets", RIDE_TYPE_TOILETS }, + { "ferris_wheel", RIDE_TYPE_FERRIS_WHEEL }, + { "motion_simulator", RIDE_TYPE_MOTION_SIMULATOR }, + { "3d_cinema", RIDE_TYPE_3D_CINEMA }, + { "top_spin", RIDE_TYPE_TOP_SPIN }, + { "space_rings", RIDE_TYPE_SPACE_RINGS }, + { "reverse_freefall_rc", RIDE_TYPE_REVERSE_FREEFALL_COASTER }, + { "lift", RIDE_TYPE_LIFT }, + { "vertical_drop_rc", RIDE_TYPE_VERTICAL_DROP_ROLLER_COASTER }, + { "cash_machine", RIDE_TYPE_CASH_MACHINE }, + { "twist", RIDE_TYPE_TWIST }, + { "haunted_house", RIDE_TYPE_HAUNTED_HOUSE }, + { "first_aid", RIDE_TYPE_FIRST_AID }, + { "circus", RIDE_TYPE_CIRCUS }, + { "ghost_train", RIDE_TYPE_GHOST_TRAIN }, + { "twister_rc", RIDE_TYPE_TWISTER_ROLLER_COASTER }, + { "wooden_rc", RIDE_TYPE_WOODEN_ROLLER_COASTER }, + { "side_friction", RIDE_TYPE_SIDE_FRICTION_ROLLER_COASTER }, + { "steel_wild_mouse", RIDE_TYPE_STEEL_WILD_MOUSE }, + { "multi_dimension_rc", RIDE_TYPE_MULTI_DIMENSION_ROLLER_COASTER }, + { "flying_rc", RIDE_TYPE_FLYING_ROLLER_COASTER }, + { "virginia_reel", RIDE_TYPE_VIRGINIA_REEL }, + { "splash_boats", RIDE_TYPE_SPLASH_BOATS }, + { "mini_helicopters", RIDE_TYPE_MINI_HELICOPTERS }, + { "lay_down_rc", RIDE_TYPE_LAY_DOWN_ROLLER_COASTER }, + { "suspended_monorail", RIDE_TYPE_SUSPENDED_MONORAIL }, + { "reverser_rc", RIDE_TYPE_REVERSER_ROLLER_COASTER }, + { "heartline_twister_rc", RIDE_TYPE_HEARTLINE_TWISTER_COASTER }, + { "mini_golf", RIDE_TYPE_MINI_GOLF }, + { "giga_rc", RIDE_TYPE_GIGA_COASTER }, + { "roto_drop", RIDE_TYPE_ROTO_DROP }, + { "flying_saucers", RIDE_TYPE_FLYING_SAUCERS }, + { "crooked_house", RIDE_TYPE_CROOKED_HOUSE }, + { "monorail_cycles", RIDE_TYPE_MONORAIL_CYCLES }, + { "compact_inverted", RIDE_TYPE_COMPACT_INVERTED_COASTER }, + { "water_coaster", RIDE_TYPE_WATER_COASTER }, + { "air_powered_vertical_rc", RIDE_TYPE_AIR_POWERED_VERTICAL_COASTER }, + { "inverted_hairpin_rc", RIDE_TYPE_INVERTED_HAIRPIN_COASTER }, + { "magic_carpet", RIDE_TYPE_MAGIC_CARPET }, + { "submarine_ride", RIDE_TYPE_SUBMARINE_RIDE }, + { "river_rafts", RIDE_TYPE_RIVER_RAFTS }, + { "enterprise", RIDE_TYPE_ENTERPRISE }, + { "inverted_impulse_rc", RIDE_TYPE_INVERTED_IMPULSE_COASTER }, + { "mini_rc", RIDE_TYPE_MINI_ROLLER_COASTER }, + { "mine_ride", RIDE_TYPE_MINE_RIDE }, + { "lim_launched_rc", RIDE_TYPE_LIM_LAUNCHED_ROLLER_COASTER }, + + // TEMPORARY: + { "restroom", RIDE_TYPE_TOILETS }, + }; + auto result = LookupTable.find(s); + return (result != LookupTable.end()) ? + result->second : + RIDE_TYPE_NULL; +} + void RideObject::ReadJson(IReadObjectContext * context, const json_t * root) { printf("RideObject::ReadJson(context, root)\n"); - auto rideType = json_string_value(json_object_get(json_object_get(root, "properties"), "type")); + auto rideTypes = GetJsonStringArray(json_object_get(json_object_get(root, "properties"), "type")); auto category = json_string_value(json_object_get(json_object_get(root, "properties"), "category")); + for (size_t i = 0; i < std::min(3, rideTypes.size()); i++) + { + auto rideType = rideTypes[i]; + _legacyType.ride_type[i] = ParseRideType(rideType); + } _legacyType.shop_item = SHOP_ITEM_NONE; _legacyType.shop_item_secondary = SHOP_ITEM_NONE; - if (String::Equals(rideType, "restroom") || - String::Equals(rideType, "toilets")) // object tool should be fixed to generate toilets, not restroom. + // TEMP: + if (_legacyType.ride_type[0] == RIDE_TYPE_FOOD_STALL) { - _legacyType.ride_type[0] = RIDE_TYPE_TOILETS; - } - else if (String::Equals(rideType, "foodstall")) - { - _legacyType.ride_type[0] = RIDE_TYPE_FOOD_STALL; _legacyType.shop_item = SHOP_ITEM_ICE_CREAM; } - _legacyType.ride_type[1] = RIDE_TYPE_NULL; - _legacyType.ride_type[2] = RIDE_TYPE_NULL; - if (String::Equals(category, "stall")) { _legacyType.category[0] = RIDE_CATEGORY_SHOP; From a7a7b2f1b4f138d362fc30cff53521ed57b19223 Mon Sep 17 00:00:00 2001 From: Ted John Date: Thu, 7 Dec 2017 22:06:51 +0000 Subject: [PATCH 13/93] Fix memory corruption in ImageTable::AddImage --- src/openrct2/object/ImageTable.cpp | 44 +++++++++++++++--------------- src/openrct2/object/ImageTable.h | 5 ++-- 2 files changed, 24 insertions(+), 25 deletions(-) diff --git a/src/openrct2/object/ImageTable.cpp b/src/openrct2/object/ImageTable.cpp index 0cb48d0d56..7111113971 100644 --- a/src/openrct2/object/ImageTable.cpp +++ b/src/openrct2/object/ImageTable.cpp @@ -15,18 +15,22 @@ #pragma endregion #include +#include #include #include "../core/IStream.hpp" -#include "../core/Memory.hpp" #include "../OpenRCT2.h" #include "ImageTable.h" #include "Object.h" ImageTable::~ImageTable() { - Memory::Free(_data); - _data = nullptr; - _dataSize = 0; + if (_data == nullptr) + { + for (auto &entry : _entries) + { + delete entry.offset; + } + } } void ImageTable::Read(IReadObjectContext * context, IStream * stream) @@ -49,16 +53,17 @@ void ImageTable::Read(IReadObjectContext * context, IStream * stream) imageDataSize = (uint32)remainingBytes; } - _dataSize = imageDataSize; - _data = Memory::Reallocate(_data, _dataSize); - if (_data == nullptr) + auto dataSize = (size_t)imageDataSize; + auto data = std::make_unique(dataSize); + if (data == nullptr) { context->LogError(OBJECT_ERROR_BAD_IMAGE_TABLE, "Image table too large."); throw std::runtime_error("Image table too large."); } // Read g1 element headers - uintptr_t imageDataBase = (uintptr_t)_data; + uintptr_t imageDataBase = (uintptr_t)data.get(); + std::vector newEntries; for (uint32 i = 0; i < numImages; i++) { rct_g1_element g1Element; @@ -73,23 +78,22 @@ void ImageTable::Read(IReadObjectContext * context, IStream * stream) g1Element.flags = stream->ReadValue(); g1Element.zoomed_offset = stream->ReadValue(); - _entries.push_back(g1Element); + newEntries.push_back(g1Element); } // Read g1 element data - size_t readBytes = (size_t)stream->TryRead(_data, _dataSize); + size_t readBytes = (size_t)stream->TryRead(data.get(), dataSize); // If data is shorter than expected (some custom objects are unfortunately like that) - size_t unreadBytes = _dataSize - readBytes; + size_t unreadBytes = dataSize - readBytes; if (unreadBytes > 0) { - uint8 * ptr = (uint8*)(((uintptr_t)_data) + readBytes); - std::fill_n(ptr, unreadBytes, 0); - + std::fill_n(data.get() + readBytes, unreadBytes, 0); context->LogWarning(OBJECT_ERROR_BAD_IMAGE_TABLE, "Image table size shorter than expected."); } - // TODO validate the image data to prevent crashes in-game + _data = std::move(data); + _entries.insert(_entries.end(), newEntries.begin(), newEntries.end()); } catch (const std::exception &) { @@ -104,16 +108,12 @@ void ImageTable::AddImage(const rct_g1_element * g1) auto length = g1_calculate_data_size(g1); if (length == 0) { - newg1.offset = 0; + newg1.offset = nullptr; } else { - auto dstOffset = _dataSize; - _dataSize += length; - _data = Memory::Reallocate(_data, _dataSize); - auto dst = (uint8 *)((size_t)_data + dstOffset); - Memory::Copy(dst, g1->offset, length); - newg1.offset = dst; + newg1.offset = new uint8[length]; + std::copy_n(g1->offset, length, newg1.offset); } _entries.push_back(newg1); } diff --git a/src/openrct2/object/ImageTable.h b/src/openrct2/object/ImageTable.h index a30107ac97..c2c6c1b10a 100644 --- a/src/openrct2/object/ImageTable.h +++ b/src/openrct2/object/ImageTable.h @@ -16,9 +16,9 @@ #pragma once +#include #include #include "../common.h" - #include "../drawing/Drawing.h" interface IReadObjectContext; @@ -27,9 +27,8 @@ interface IStream; class ImageTable { private: + std::unique_ptr _data; std::vector _entries; - void * _data = nullptr; - size_t _dataSize = 0; public: ~ImageTable(); From 4fdbf1ca9392ce20d40f20d77f414c120816be18 Mon Sep 17 00:00:00 2001 From: Ted John Date: Thu, 7 Dec 2017 22:33:41 +0000 Subject: [PATCH 14/93] Parse category and shop item --- src/openrct2/object/RideObject.cpp | 93 +++++++++++++++++++++++++----- 1 file changed, 80 insertions(+), 13 deletions(-) diff --git a/src/openrct2/object/RideObject.cpp b/src/openrct2/object/RideObject.cpp index c389181fad..48e2716054 100644 --- a/src/openrct2/object/RideObject.cpp +++ b/src/openrct2/object/RideObject.cpp @@ -753,29 +753,96 @@ static uint8 ParseRideType(const std::string &s) RIDE_TYPE_NULL; } +static uint8 ParseRideCategory(const std::string &s) +{ + static const std::unordered_map LookupTable + { + { "transport", RIDE_CATEGORY_TRANSPORT }, + { "gentle", RIDE_CATEGORY_GENTLE }, + { "rollercoaster", RIDE_CATEGORY_ROLLERCOASTER }, + { "thrill", RIDE_CATEGORY_THRILL }, + { "water", RIDE_CATEGORY_WATER }, + { "stall", RIDE_CATEGORY_SHOP }, + }; + auto result = LookupTable.find(s); + return (result != LookupTable.end()) ? + result->second : + RIDE_CATEGORY_TRANSPORT; +} + +static uint8 ParseShopItem(const std::string &s) +{ + static const std::unordered_map LookupTable + { + { "burger", SHOP_ITEM_BURGER }, + { "fries", SHOP_ITEM_CHIPS }, + { "icecream", SHOP_ITEM_ICE_CREAM }, + { "cottoncandy", SHOP_ITEM_CANDYFLOSS }, + { "pizza", SHOP_ITEM_PIZZA }, + { "popcorn", SHOP_ITEM_POPCORN }, + { "hotdog", SHOP_ITEM_HOT_DOG }, + { "seafood", SHOP_ITEM_TENTACLE }, + { "candyapple", SHOP_ITEM_CANDY_APPLE }, + { "donut", SHOP_ITEM_DONUT }, + { "chicken", SHOP_ITEM_CHICKEN }, + { "pretzel", SHOP_ITEM_PRETZEL }, + { "funnelcake", SHOP_ITEM_FUNNEL_CAKE }, + { "beefnoodles", SHOP_ITEM_BEEF_NOODLES }, + { "friednoodles", SHOP_ITEM_FRIED_RICE_NOODLES }, + { "wontonsoup", SHOP_ITEM_WONTON_SOUP }, + { "meatballsoup", SHOP_ITEM_MEATBALL_SOUP }, + { "subsandwich", SHOP_ITEM_SUB_SANDWICH }, + { "cookies", SHOP_ITEM_COOKIE }, + { "roastsausage", SHOP_ITEM_ROAST_SAUSAGE }, + { "cola", SHOP_ITEM_DRINK }, + { "coffee", SHOP_ITEM_COFFEE }, + { "lemonade", SHOP_ITEM_LEMONADE }, + { "hotchocolate", SHOP_ITEM_CHOCOLATE }, + { "icedtea", SHOP_ITEM_ICED_TEA }, + { "fruitjuice", SHOP_ITEM_FRUIT_JUICE }, + { "soybeanmilk", SHOP_ITEM_SOYBEAN_MILK }, + { "sujongkwa", SHOP_ITEM_SU_JONGKWA }, + { "balloon", SHOP_ITEM_BALLOON }, + { "plushtoy", SHOP_ITEM_TOY }, + { "map", SHOP_ITEM_MAP }, + { "onridephoto", SHOP_ITEM_PHOTO }, + { "umbrella", SHOP_ITEM_UMBRELLA }, + { "voucher", SHOP_ITEM_VOUCHER }, + { "hat", SHOP_ITEM_HAT }, + { "tshirt", SHOP_ITEM_TSHIRT }, + { "sunglasses", SHOP_ITEM_SUNGLASSES }, + }; + auto result = LookupTable.find(s); + return (result != LookupTable.end()) ? + result->second : + SHOP_ITEM_NONE; +} + void RideObject::ReadJson(IReadObjectContext * context, const json_t * root) { - printf("RideObject::ReadJson(context, root)\n"); auto rideTypes = GetJsonStringArray(json_object_get(json_object_get(root, "properties"), "type")); - auto category = json_string_value(json_object_get(json_object_get(root, "properties"), "category")); - - for (size_t i = 0; i < std::min(3, rideTypes.size()); i++) + for (size_t i = 0; i < std::min(MAX_RIDE_TYPES_PER_RIDE_ENTRY, rideTypes.size()); i++) { - auto rideType = rideTypes[i]; - _legacyType.ride_type[i] = ParseRideType(rideType); + _legacyType.ride_type[i] = ParseRideType(rideTypes[i]); } + + auto rideCategories = GetJsonStringArray(json_object_get(json_object_get(root, "properties"), "category")); + for (size_t i = 0; i < std::min(MAX_CATEGORIES_PER_RIDE, rideCategories.size()); i++) + { + _legacyType.category[0] = ParseRideCategory(rideCategories[i]); + } + + // Shop item + auto rideSells = GetJsonStringArray(json_object_get(json_object_get(root, "properties"), "sells")); _legacyType.shop_item = SHOP_ITEM_NONE; _legacyType.shop_item_secondary = SHOP_ITEM_NONE; - - // TEMP: - if (_legacyType.ride_type[0] == RIDE_TYPE_FOOD_STALL) + if (rideSells.size() >= 1) { - _legacyType.shop_item = SHOP_ITEM_ICE_CREAM; + _legacyType.shop_item = ParseShopItem(rideSells[0]); } - if (String::Equals(category, "stall")) + if (rideSells.size() >= 2) { - _legacyType.category[0] = RIDE_CATEGORY_SHOP; - _legacyType.category[1] = RIDE_CATEGORY_SHOP; + _legacyType.shop_item_secondary = ParseShopItem(rideSells[1]); } _legacyType.flags |= RIDE_ENTRY_FLAG_SEPARATE_RIDE; From 1e4a8c0da7c9a2ba46a66ce4a9bfd45154c023e2 Mon Sep 17 00:00:00 2001 From: Ted John Date: Thu, 7 Dec 2017 23:29:01 +0000 Subject: [PATCH 15/93] Refactor common JSON methods to new helper namespace --- OpenRCT2.xcodeproj/project.pbxproj | 50 +++++++ src/openrct2/object/ObjectJsonHelpers.cpp | 160 ++++++++++++++++++++++ src/openrct2/object/ObjectJsonHelpers.h | 30 ++++ src/openrct2/object/RideObject.cpp | 139 +------------------ 4 files changed, 245 insertions(+), 134 deletions(-) create mode 100644 src/openrct2/object/ObjectJsonHelpers.cpp create mode 100644 src/openrct2/object/ObjectJsonHelpers.h diff --git a/OpenRCT2.xcodeproj/project.pbxproj b/OpenRCT2.xcodeproj/project.pbxproj index 15b08849d4..5b3698965a 100644 --- a/OpenRCT2.xcodeproj/project.pbxproj +++ b/OpenRCT2.xcodeproj/project.pbxproj @@ -25,6 +25,44 @@ 4C3B423820591513000C5BB7 /* StdInOutConsole.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C3B423720591513000C5BB7 /* StdInOutConsole.cpp */; }; 4C93F1AD1F8CD9F000A9330D /* Input.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C93F1AC1F8CD9F000A9330D /* Input.cpp */; }; 4C93F1AF1F8CD9F600A9330D /* KeyboardShortcut.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C93F1AE1F8CD9F600A9330D /* KeyboardShortcut.cpp */; }; + 4C93F1BA1F8E185600A9330D /* Award.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C93F1B01F8E185600A9330D /* Award.cpp */; }; + 4C93F1BB1F8E185600A9330D /* Finance.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C93F1B21F8E185600A9330D /* Finance.cpp */; }; + 4C93F1BC1F8E185600A9330D /* Marketing.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C93F1B41F8E185600A9330D /* Marketing.cpp */; }; + 4C93F1BD1F8E185600A9330D /* NewsItem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C93F1B61F8E185600A9330D /* NewsItem.cpp */; }; + 4C93F1BE1F8E185600A9330D /* Research.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C93F1B81F8E185600A9330D /* Research.cpp */; }; + 4CB832AB1EFFB8D100B88761 /* ttf_sdlport.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CB832A81EFFB8D100B88761 /* ttf_sdlport.c */; }; + 4CC4B8E41FE00C4200660D62 /* CmdlineSprite.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CC4B8E21FE00C4100660D62 /* CmdlineSprite.cpp */; }; + 4CC4B8E71FE00C4E00660D62 /* Diagnostic.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CC4B8E51FE00C4E00660D62 /* Diagnostic.cpp */; }; + 4CC4B8ED1FE00C5D00660D62 /* Intro.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CC4B8EA1FE00C5D00660D62 /* Intro.cpp */; }; + 4CE462411FD0710E0001CD98 /* Game.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CE4623F1FD0710E0001CD98 /* Game.cpp */; }; + 4CE462451FD161360001CD98 /* Platform.Android.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CE462441FD161360001CD98 /* Platform.Android.cpp */; }; + 4CE4624A1FD1613D0001CD98 /* Platform.Linux.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CE462461FD1613D0001CD98 /* Platform.Linux.cpp */; }; + 4CE4624B1FD1613D0001CD98 /* Platform.macOS.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CE462471FD1613D0001CD98 /* Platform.macOS.cpp */; }; + 4CE4624C1FD1613D0001CD98 /* Platform.Posix.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CE462481FD1613D0001CD98 /* Platform.Posix.cpp */; }; + 4CE4624D1FD1613D0001CD98 /* Platform.Win32.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CE462491FD1613D0001CD98 /* Platform.Win32.cpp */; }; + 4CE9AAAD1FDA7B14004093C6 /* ObjectJsonHelpers.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CE9AAAB1FDA7B14004093C6 /* ObjectJsonHelpers.cpp */; }; + 4CF788C01F1B787700C611BF /* Painter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CF788BE1F1B787700C611BF /* Painter.cpp */; }; + 4CFBCD5E1F27CD8000D74FB6 /* SmallScenery.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CFBCD5D1F27CD8000D74FB6 /* SmallScenery.cpp */; }; + 4CFE4E801F90A3F1005243C2 /* Peep.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CFE4E7B1F90A3F1005243C2 /* Peep.cpp */; }; + 4CFE4E811F90A3F1005243C2 /* PeepData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CFE4E7D1F90A3F1005243C2 /* PeepData.cpp */; }; + 4CFE4E821F90A3F1005243C2 /* Staff.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CFE4E7E1F90A3F1005243C2 /* Staff.cpp */; }; + 4CFE4E851F90AF41005243C2 /* Vehicle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CFE4E831F90AF41005243C2 /* Vehicle.cpp */; }; + 4CFE4E891F950164005243C2 /* TrackData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CFE4E861F950164005243C2 /* TrackData.cpp */; }; + 4CFE4E8A1F950164005243C2 /* TrackDataOld.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CFE4E881F950164005243C2 /* TrackDataOld.cpp */; }; + 4CFE4E901F9625B0005243C2 /* Track.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CFE4E8E1F9625B0005243C2 /* Track.cpp */; }; + C606CCC01DB4054000FE4015 /* FunctionCall.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C606CCAE1DB4054000FE4015 /* FunctionCall.cpp */; }; + C606CCC11DB4054000FE4015 /* generate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C606CCB01DB4054000FE4015 /* generate.cpp */; }; + C606CCC41DB4054000FE4015 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C606CCB41DB4054000FE4015 /* main.cpp */; }; + C606CCC51DB4054000FE4015 /* PaintIntercept.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C606CCB51DB4054000FE4015 /* PaintIntercept.cpp */; }; + C606CCC61DB4054000FE4015 /* Printer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C606CCB61DB4054000FE4015 /* Printer.cpp */; }; + C606CCC71DB4054000FE4015 /* String.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C606CCB81DB4054000FE4015 /* String.cpp */; }; + C606CCC81DB4054000FE4015 /* TestTrack.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C606CCBA1DB4054000FE4015 /* TestTrack.cpp */; }; + C606CCC91DB4054000FE4015 /* Utils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C606CCBC1DB4054000FE4015 /* Utils.cpp */; }; + C606CCCE1DB427A000FE4015 /* GeneralSupportHeightCall.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C606CCCA1DB427A000FE4015 /* GeneralSupportHeightCall.cpp */; }; + C606CCCF1DB427A000FE4015 /* SegmentSupportHeightCall.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C606CCCC1DB427A000FE4015 /* SegmentSupportHeightCall.cpp */; }; + C606CCD21DB4D7C800FE4015 /* SideTunnelCall.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C606CCD01DB4D7C800FE4015 /* SideTunnelCall.cpp */; }; + C606CCD51DB4DD6C00FE4015 /* VerticalTunnelCall.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C606CCD31DB4DD6C00FE4015 /* VerticalTunnelCall.cpp */; }; + C606CD261DB5120C00FE4015 /* TestPaint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C606CD231DB5120900FE4015 /* TestPaint.cpp */; }; C61ADB1F1FB6A0A70024F2EF /* TopToolbar.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C61ADB1E1FB6A0A60024F2EF /* TopToolbar.cpp */; }; C61ADB211FB7DC060024F2EF /* Scenery.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C61ADB201FB7DC060024F2EF /* Scenery.cpp */; }; C61ADB231FBBCB8B0024F2EF /* GameBottomToolbar.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C61ADB221FBBCB8A0024F2EF /* GameBottomToolbar.cpp */; }; @@ -847,6 +885,11 @@ 4CE462461FD1613D0001CD98 /* Platform.Linux.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Platform.Linux.cpp; sourceTree = ""; }; 4CE462481FD1613D0001CD98 /* Platform.Posix.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Platform.Posix.cpp; sourceTree = ""; }; 4CE462491FD1613D0001CD98 /* Platform.Win32.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Platform.Win32.cpp; sourceTree = ""; }; + 4CE9AAAB1FDA7B14004093C6 /* ObjectJsonHelpers.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ObjectJsonHelpers.cpp; sourceTree = ""; }; + 4CE9AAAC1FDA7B14004093C6 /* ObjectJsonHelpers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ObjectJsonHelpers.h; sourceTree = ""; }; + 4CF788BE1F1B787700C611BF /* Painter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Painter.cpp; sourceTree = ""; }; + 4CF788BF1F1B787700C611BF /* Painter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Painter.h; sourceTree = ""; }; + 4CFBCD5D1F27CD8000D74FB6 /* SmallScenery.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SmallScenery.cpp; sourceTree = ""; }; 4CFE4E7B1F90A3F1005243C2 /* Peep.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Peep.cpp; sourceTree = ""; }; 4CFE4E7C1F90A3F1005243C2 /* Peep.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Peep.h; sourceTree = ""; }; 4CFE4E7D1F90A3F1005243C2 /* PeepData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PeepData.cpp; sourceTree = ""; }; @@ -2083,6 +2126,8 @@ 4C7B53A21FFC15ED00A52E21 /* ObjectLimits.h */, 4C7B53A31FFC180400A52E21 /* ObjectList.cpp */, 4C7B53A41FFC180400A52E21 /* ObjectList.h */, + 4CE9AAAB1FDA7B14004093C6 /* ObjectJsonHelpers.cpp */, + 4CE9AAAC1FDA7B14004093C6 /* ObjectJsonHelpers.h */, F76C84221EC4E7CC00FA49E2 /* ObjectManager.cpp */, F76C84231EC4E7CC00FA49E2 /* ObjectManager.h */, F76C84241EC4E7CC00FA49E2 /* ObjectRepository.cpp */, @@ -3043,6 +3088,11 @@ C68313D51FDB4F4C006DB3D8 /* Graph.cpp in Sources */, C685E51D1F8907850090598F /* Research.cpp in Sources */, C64644FB1F3FA4120026AC2D /* EditorScenarioOptions.cpp in Sources */, + 4C6A66AB1FE2787700694CB6 /* SmallScenery.cpp in Sources */, + 4CE9AAAD1FDA7B14004093C6 /* ObjectJsonHelpers.cpp in Sources */, + F775F5371EE3724F001F00E7 /* DummyAudioContext.cpp in Sources */, + 4C5DFF421FAC69D200CB093A /* Date.cpp in Sources */, + 4C93F13C1F8B744400A9330D /* BolligerMabillardTrack.cpp in Sources */, C654DF321F69C0430040F43D /* InstallTrack.cpp in Sources */, C64644FF1F3FA4120026AC2D /* StaffList.cpp in Sources */, C6D2BEE81F9BAACE008B557C /* MazeConstruction.cpp in Sources */, diff --git a/src/openrct2/object/ObjectJsonHelpers.cpp b/src/openrct2/object/ObjectJsonHelpers.cpp new file mode 100644 index 0000000000..21dc30e661 --- /dev/null +++ b/src/openrct2/object/ObjectJsonHelpers.cpp @@ -0,0 +1,160 @@ +#pragma region Copyright (c) 2014-2017 OpenRCT2 Developers +/***************************************************************************** + * OpenRCT2, an open source clone of Roller Coaster Tycoon 2. + * + * OpenRCT2 is the work of many authors, a full list can be found in contributors.md + * For more information, visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * A full copy of the GNU General Public License can be found in licence.txt + *****************************************************************************/ +#pragma endregion + +#include "../Context.h" +#include "../core/Memory.hpp" +#include "../core/Path.hpp" +#include "../core/String.hpp" +#include "../PlatformEnvironment.h" +#include "../sprites.h" +#include "Object.h" +#include "ObjectFactory.h" +#include "ObjectJsonHelpers.h" + +using namespace OpenRCT2; + +namespace ObjectJsonHelpers +{ + std::vector GetJsonStringArray(const json_t * arr) + { + std::vector result; + if (json_is_array(arr)) + { + auto count = json_array_size(arr); + for (size_t i = 0; i < count; i++) + { + auto element = json_string_value(json_array_get(arr, i)); + result.push_back(element); + } + } + else if (json_is_string(arr)) + { + result.push_back(json_string_value(arr)); + } + return result; + } + + static std::vector ParseRange(std::string s) + { + // Currently only supports [###] or [###..###] + std::vector result; + if (s.length() >= 3 && s[0] == '[' && s[s.length() - 1] == ']') + { + s = s.substr(1, s.length() - 2); + auto parts = String::Split(s, ".."); + if (parts.size() == 1) + { + result.push_back(std::stoi(parts[0])); + } + else + { + auto left = std::stoi(parts[0]); + auto right = std::stoi(parts[1]); + if (left <= right) + { + for (auto i = left; i <= right; i++) + { + result.push_back(i); + } + } + else + { + for (auto i = right; i >= left; i--) + { + result.push_back(i); + } + } + } + } + return result; + } + + static std::vector LoadObjectImages(const std::string &name) + { + std::vector result; + const auto env = GetContext()->GetPlatformEnvironment(); + auto objectsPath = env->GetDirectoryPath(DIRBASE::RCT2, DIRID::OBJECT); + auto objectPath = Path::Combine(objectsPath, name); + auto obj = ObjectFactory::CreateObjectFromLegacyFile(objectPath.c_str()); + auto imgTable = static_cast(obj)->GetImageTable(); + auto numImages = imgTable->GetCount(); + auto images = imgTable->GetImages(); + for (uint32 i = 0; i < numImages; i++) + { + auto g1 = images[i]; + auto length = g1_calculate_data_size(&g1); + g1.offset = Memory::Duplicate(g1.offset, length); + result.push_back(g1); + } + delete obj; + return result; + } + + static std::vector ParseImages(std::string s) + { + std::vector result; + if (s.empty()) + { + rct_g1_element emptyg1 = { 0 }; + result.push_back(emptyg1); + } + else if (String::StartsWith(s, "$CSG")) + { + if (is_csg_loaded()) + { + auto range = ParseRange(s.substr(4)); + if (range.size() > 0) + { + for (auto i : range) + { + auto g1 = *gfx_get_g1_element(SPR_CSG_BEGIN + i); + auto length = g1_calculate_data_size(&g1); + g1.offset = Memory::Duplicate(g1.offset, length); + result.push_back(g1); + } + } + } + } + else if (String::StartsWith(s, "$RCT2:OBJDATA/")) + { + auto name = s.substr(14); + auto rangeStart = name.find('['); + auto range = std::vector({ 0 }); + if (rangeStart != std::string::npos) + { + range = ParseRange(name.substr(rangeStart)); + name = name.substr(0, rangeStart); + } + return LoadObjectImages(name); + } + return result; + } + + void LoadImages(const json_t * root, ImageTable &imageTable) + { + auto jsonImages = json_object_get(root, "images"); + auto imageElements = GetJsonStringArray(jsonImages); + for (const auto &ie : imageElements) + { + auto images = ParseImages(ie); + for (const auto &g1 : images) + { + imageTable.AddImage(&g1); + Memory::Free(g1.offset); + } + } + } +} diff --git a/src/openrct2/object/ObjectJsonHelpers.h b/src/openrct2/object/ObjectJsonHelpers.h new file mode 100644 index 0000000000..b5565d5709 --- /dev/null +++ b/src/openrct2/object/ObjectJsonHelpers.h @@ -0,0 +1,30 @@ +#pragma region Copyright (c) 2014-2017 OpenRCT2 Developers +/***************************************************************************** + * OpenRCT2, an open source clone of Roller Coaster Tycoon 2. + * + * OpenRCT2 is the work of many authors, a full list can be found in contributors.md + * For more information, visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * A full copy of the GNU General Public License can be found in licence.txt + *****************************************************************************/ +#pragma endregion + +#pragma once + +#include +#include +#include "../common.h" +#include "../core/Json.hpp" +#include "../drawing/drawing.h" +#include "ImageTable.h" + +namespace ObjectJsonHelpers +{ + std::vector GetJsonStringArray(const json_t * arr); + void LoadImages(const json_t * root, ImageTable &imageTable); +}; diff --git a/src/openrct2/object/RideObject.cpp b/src/openrct2/object/RideObject.cpp index 48e2716054..ad69fc5e9a 100644 --- a/src/openrct2/object/RideObject.cpp +++ b/src/openrct2/object/RideObject.cpp @@ -16,10 +16,8 @@ #include #include -#include "../Context.h" #include "../core/IStream.hpp" #include "../core/Memory.hpp" -#include "../core/Path.hpp" #include "../core/String.hpp" #include "../OpenRCT2.h" #include "ObjectRepository.h" @@ -32,9 +30,7 @@ #include "../ride/Ride.h" #include "../ride/Track.h" #include "../OpenRCT2.h" -#include "../PlatformEnvironment.h" -#include "../sprites.h" -#include "ObjectFactory.h" +#include "ObjectJsonHelpers.h" #include "ObjectRepository.h" #include "RideObject.h" @@ -545,121 +541,6 @@ uint8 RideObject::CalculateNumHorizontalFrames(const rct_ride_entry_vehicle * ve return numHorizontalFrames; } -static std::vector ParseRange(std::string s) -{ - // Currently only supports [###] or [###..###] - std::vector result; - if (s.length() >= 3 && s[0] == '[' && s[s.length() - 1] == ']') - { - s = s.substr(1, s.length() - 2); - auto parts = String::Split(s, ".."); - if (parts.size() == 1) - { - result.push_back(std::stoi(parts[0])); - } - else - { - auto left = std::stoi(parts[0]); - auto right = std::stoi(parts[1]); - if (left <= right) - { - for (auto i = left; i <= right; i++) - { - result.push_back(i); - } - } - else - { - for (auto i = right; i >= left; i--) - { - result.push_back(i); - } - } - } - } - return result; -} - -static std::vector LoadObjectImages(const std::string &name) -{ - std::vector result; - const auto env = GetContext()->GetPlatformEnvironment(); - auto objectsPath = env->GetDirectoryPath(DIRBASE::RCT2, DIRID::OBJECT); - auto objectPath = Path::Combine(objectsPath, name); - auto obj = ObjectFactory::CreateObjectFromLegacyFile(objectPath.c_str()); - auto imgTable = static_cast(obj)->GetImageTable(); - auto numImages = imgTable->GetCount(); - auto images = imgTable->GetImages(); - for (uint32 i = 0; i < numImages; i++) - { - auto g1 = images[i]; - auto length = g1_calculate_data_size(&g1); - g1.offset = Memory::Duplicate(g1.offset, length); - result.push_back(g1); - } - delete obj; - return result; -} - -static std::vector ParseImages(std::string s) -{ - std::vector result; - if (s.empty()) - { - rct_g1_element emptyg1 = { 0 }; - result.push_back(emptyg1); - } - else if (String::StartsWith(s, "$CSG")) - { - if (is_csg_loaded()) - { - auto range = ParseRange(s.substr(4)); - if (range.size() > 0) - { - for (auto i : range) - { - auto g1 = *gfx_get_g1_element(SPR_CSG_BEGIN + i); - auto length = g1_calculate_data_size(&g1); - g1.offset = Memory::Duplicate(g1.offset, length); - result.push_back(g1); - } - } - } - } - else if (String::StartsWith(s, "$RCT2:OBJDATA/")) - { - auto name = s.substr(14); - auto rangeStart = name.find('['); - auto range = std::vector({ 0 }); - if (rangeStart != std::string::npos) - { - range = ParseRange(name.substr(rangeStart)); - name = name.substr(0, rangeStart); - } - return LoadObjectImages(name); - } - return result; -} - -static std::vector GetJsonStringArray(const json_t * arr) -{ - std::vector result; - if (json_is_array(arr)) - { - auto count = json_array_size(arr); - for (size_t i = 0; i < count; i++) - { - auto element = json_string_value(json_array_get(arr, i)); - result.push_back(element); - } - } - else if (json_is_string(arr)) - { - result.push_back(json_string_value(arr)); - } - return result; -} - static uint8 ParseRideType(const std::string &s) { static const std::unordered_map LookupTable @@ -820,20 +701,20 @@ static uint8 ParseShopItem(const std::string &s) void RideObject::ReadJson(IReadObjectContext * context, const json_t * root) { - auto rideTypes = GetJsonStringArray(json_object_get(json_object_get(root, "properties"), "type")); + auto rideTypes = ObjectJsonHelpers::GetJsonStringArray(json_object_get(json_object_get(root, "properties"), "type")); for (size_t i = 0; i < std::min(MAX_RIDE_TYPES_PER_RIDE_ENTRY, rideTypes.size()); i++) { _legacyType.ride_type[i] = ParseRideType(rideTypes[i]); } - auto rideCategories = GetJsonStringArray(json_object_get(json_object_get(root, "properties"), "category")); + auto rideCategories = ObjectJsonHelpers::GetJsonStringArray(json_object_get(json_object_get(root, "properties"), "category")); for (size_t i = 0; i < std::min(MAX_CATEGORIES_PER_RIDE, rideCategories.size()); i++) { _legacyType.category[0] = ParseRideCategory(rideCategories[i]); } // Shop item - auto rideSells = GetJsonStringArray(json_object_get(json_object_get(root, "properties"), "sells")); + auto rideSells = ObjectJsonHelpers::GetJsonStringArray(json_object_get(json_object_get(root, "properties"), "sells")); _legacyType.shop_item = SHOP_ITEM_NONE; _legacyType.shop_item_secondary = SHOP_ITEM_NONE; if (rideSells.size() >= 1) @@ -858,17 +739,7 @@ void RideObject::ReadJson(IReadObjectContext * context, const json_t * root) stringTable->SetString(3, 0, "Vehicle"); auto imageTable = GetImageTable(); - auto jsonImages = json_object_get(root, "images"); - auto imageElements = GetJsonStringArray(jsonImages); - for (const auto &ie : imageElements) - { - auto images = ParseImages(ie); - for (const auto &g1 : images) - { - imageTable->AddImage(&g1); - Memory::Free(g1.offset); - } - } + ObjectJsonHelpers::LoadImages(root, *imageTable); rct_ride_entry_vehicle * vehicle0 = &_legacyType.vehicles[0]; vehicle0->sprite_flags |= VEHICLE_SPRITE_FLAG_FLAT; From 2d037fb3aefbf8cd46b43a4b2f2c021c0de70320 Mon Sep 17 00:00:00 2001 From: Ted John Date: Thu, 7 Dec 2017 23:50:44 +0000 Subject: [PATCH 16/93] Read JSON for park entrance objects --- src/openrct2/object/EntranceObject.cpp | 20 ++++++++++++++++++-- src/openrct2/object/EntranceObject.h | 1 + src/openrct2/object/ObjectFactory.cpp | 19 ++++++++++++++++--- 3 files changed, 35 insertions(+), 5 deletions(-) diff --git a/src/openrct2/object/EntranceObject.cpp b/src/openrct2/object/EntranceObject.cpp index 1d31029372..814a34fedf 100644 --- a/src/openrct2/object/EntranceObject.cpp +++ b/src/openrct2/object/EntranceObject.cpp @@ -16,10 +16,10 @@ #include "../core/IStream.hpp" #include "../core/String.hpp" -#include "EntranceObject.h" - #include "../drawing/Drawing.h" #include "../localisation/Localisation.h" +#include "EntranceObject.h" +#include "ObjectJsonHelpers.h" void EntranceObject::ReadLegacy(IReadObjectContext * context, IStream * stream) { @@ -65,3 +65,19 @@ void EntranceObject::DrawPreview(rct_drawpixelinfo * dpi, sint32 width, sint32 h gfx_draw_sprite(dpi, imageId + 0, x + 0, y + 28, 0); gfx_draw_sprite(dpi, imageId + 2, x + 32, y + 44, 0); } + +void EntranceObject::ReadJson(IReadObjectContext * context, const json_t * root) +{ + // Strings + auto stringTable = GetStringTable(); + auto jsonStrings = json_object_get(root, "strings"); + auto jsonName = json_object_get(jsonStrings, "name"); + stringTable->SetString(0, 0, json_string_value(json_object_get(jsonName, "en-GB"))); + + auto properties = json_object_get(root, "properties"); + _legacyType.scrolling_mode = json_integer_value(json_object_get(properties, "scrollingMode")); + _legacyType.text_height = json_integer_value(json_object_get(properties, "textHeight")); + + auto imageTable = GetImageTable(); + ObjectJsonHelpers::LoadImages(root, *imageTable); +} diff --git a/src/openrct2/object/EntranceObject.h b/src/openrct2/object/EntranceObject.h index 4af4a02985..6d6c0b65cb 100644 --- a/src/openrct2/object/EntranceObject.h +++ b/src/openrct2/object/EntranceObject.h @@ -31,6 +31,7 @@ public: void * GetLegacyData() override { return &_legacyType; } void ReadLegacy(IReadObjectContext * context, IStream * stream) override; + void ReadJson(IReadObjectContext * context, const json_t * root) override; void Load() override; void Unload() override; diff --git a/src/openrct2/object/ObjectFactory.cpp b/src/openrct2/object/ObjectFactory.cpp index 7adac8c280..7adbf45148 100644 --- a/src/openrct2/object/ObjectFactory.cpp +++ b/src/openrct2/object/ObjectFactory.cpp @@ -205,6 +205,19 @@ namespace ObjectFactory return result; } + static uint8 ParseObjectType(const std::string &s) + { + if (s == "ride") + { + return OBJECT_TYPE_RIDE; + } + else if (s == "park_entrance") + { + return OBJECT_TYPE_PARK_ENTRANCE; + } + return 0xFF; + } + Object * CreateObjectFromJsonFile(const std::string &path) { log_verbose("CreateObjectFromJsonFile(\"%s\")", path.c_str()); @@ -216,8 +229,8 @@ namespace ObjectFactory auto jObjectType = json_object_get(jRoot, "objectType"); if (json_is_string(jObjectType)) { - auto objectType = std::string(json_string_value(jObjectType)); - if (objectType == "ride") + auto objectType = ParseObjectType(json_string_value(jObjectType)); + if (objectType != 0xFF) { auto id = json_string_value(json_object_get(jRoot, "id")); @@ -233,7 +246,7 @@ namespace ObjectFactory auto minLength = std::min(8, originalName.length()); memcpy(entry.name, originalName.c_str(), minLength); - result = new RideObject(entry); + result = CreateObject(entry); auto readContext = ReadObjectContext(id); result->ReadJson(&readContext, jRoot); if (readContext.WasError()) From 27a055653c31c011409793aa2a7a107eb73ffdab Mon Sep 17 00:00:00 2001 From: Michael Steenbeek Date: Fri, 8 Dec 2017 08:08:46 +0100 Subject: [PATCH 17/93] Fix rebase errors --- src/openrct2/object/RideObject.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/openrct2/object/RideObject.cpp b/src/openrct2/object/RideObject.cpp index ad69fc5e9a..58aecd13c8 100644 --- a/src/openrct2/object/RideObject.cpp +++ b/src/openrct2/object/RideObject.cpp @@ -553,7 +553,7 @@ static uint8 ParseRideType(const std::string &s) { "miniature_railway", RIDE_TYPE_MINIATURE_RAILWAY }, { "monorail", RIDE_TYPE_MONORAIL }, { "mini_suspended_rc", RIDE_TYPE_MINI_SUSPENDED_COASTER }, - { "boat_hire", RIDE_TYPE_BOAT_RIDE }, + { "boat_hire", RIDE_TYPE_BOAT_HIRE }, { "wooden_wild_mouse", RIDE_TYPE_WOODEN_WILD_MOUSE }, { "steeplechase", RIDE_TYPE_STEEPLECHASE }, { "car_ride", RIDE_TYPE_CAR_RIDE }, @@ -663,8 +663,8 @@ static uint8 ParseShopItem(const std::string &s) { "popcorn", SHOP_ITEM_POPCORN }, { "hotdog", SHOP_ITEM_HOT_DOG }, { "seafood", SHOP_ITEM_TENTACLE }, - { "candyapple", SHOP_ITEM_CANDY_APPLE }, - { "donut", SHOP_ITEM_DONUT }, + { "candyapple", SHOP_ITEM_TOFFEE_APPLE }, + { "donut", SHOP_ITEM_DOUGHNUT }, { "chicken", SHOP_ITEM_CHICKEN }, { "pretzel", SHOP_ITEM_PRETZEL }, { "funnelcake", SHOP_ITEM_FUNNEL_CAKE }, From d27a90f06803b074ab79dfe6da4e4ea7dc17c050 Mon Sep 17 00:00:00 2001 From: Ted John Date: Fri, 8 Dec 2017 18:27:30 +0000 Subject: [PATCH 18/93] Implement footpath JSON reading --- src/openrct2/object/FootpathObject.cpp | 41 +++++++++++++++++++++-- src/openrct2/object/FootpathObject.h | 1 + src/openrct2/object/ObjectFactory.cpp | 4 +++ src/openrct2/object/ObjectJsonHelpers.cpp | 7 ++++ src/openrct2/object/ObjectJsonHelpers.h | 1 + 5 files changed, 52 insertions(+), 2 deletions(-) diff --git a/src/openrct2/object/FootpathObject.cpp b/src/openrct2/object/FootpathObject.cpp index a57ee453ae..f817f2ab51 100644 --- a/src/openrct2/object/FootpathObject.cpp +++ b/src/openrct2/object/FootpathObject.cpp @@ -15,11 +15,11 @@ #pragma endregion #include "../core/IStream.hpp" -#include "FootpathObject.h" - #include "../drawing/Drawing.h" #include "../localisation/Language.h" #include "../world/Footpath.h" +#include "FootpathObject.h" +#include "ObjectJsonHelpers.h" void FootpathObject::ReadLegacy(IReadObjectContext * context, IStream * stream) { @@ -63,3 +63,40 @@ void FootpathObject::DrawPreview(rct_drawpixelinfo * dpi, sint32 width, sint32 h gfx_draw_sprite(dpi, _legacyType.image + 71, x - 49, y - 17, 0); gfx_draw_sprite(dpi, _legacyType.image + 72, x + 4, y - 17, 0); } + +static uint8 ParseSupportType(const std::string &s) +{ + if (s == "pole") return FOOTPATH_ENTRY_SUPPORT_TYPE_POLE; + else /* if (s == "box") */ return FOOTPATH_ENTRY_SUPPORT_TYPE_BOX; +} + +void FootpathObject::ReadJson(IReadObjectContext * context, const json_t * root) +{ + // Strings + auto stringTable = GetStringTable(); + auto jsonStrings = json_object_get(root, "strings"); + auto jsonName = json_object_get(jsonStrings, "name"); + stringTable->SetString(0, 0, json_string_value(json_object_get(jsonName, "en-GB"))); + + auto properties = json_object_get(root, "properties"); + _legacyType.support_type = ParseSupportType(ObjectJsonHelpers::GetString(json_object_get(properties, "supportType"))); + _legacyType.scrolling_mode = json_integer_value(json_object_get(properties, "scrollingMode")); + + // Flags + _legacyType.flags = 0; + if (json_boolean_value(json_object_get(properties, "hasSupportImages"))) + { + _legacyType.flags |= FOOTPATH_ENTRY_FLAG_HAS_SUPPORT_BASE_SPRITE; + } + if (json_boolean_value(json_object_get(properties, "hasElevatedPathImages"))) + { + _legacyType.flags |= FOOTPATH_ENTRY_FLAG_HAS_PATH_BASE_SPRITE; + } + if (json_boolean_value(json_object_get(properties, "editorOnly"))) + { + _legacyType.flags |= FOOTPATH_ENTRY_FLAG_SHOW_ONLY_IN_SCENARIO_EDITOR; + } + + auto imageTable = GetImageTable(); + ObjectJsonHelpers::LoadImages(root, *imageTable); +} diff --git a/src/openrct2/object/FootpathObject.h b/src/openrct2/object/FootpathObject.h index b1513ab491..8d4cbecf00 100644 --- a/src/openrct2/object/FootpathObject.h +++ b/src/openrct2/object/FootpathObject.h @@ -31,6 +31,7 @@ public: void * GetLegacyData() override { return &_legacyType; } void ReadLegacy(IReadObjectContext * context, IStream * stream) override; + void ReadJson(IReadObjectContext * context, const json_t * root) override; void Load() override; void Unload() override; diff --git a/src/openrct2/object/ObjectFactory.cpp b/src/openrct2/object/ObjectFactory.cpp index 7adbf45148..6fefc0840d 100644 --- a/src/openrct2/object/ObjectFactory.cpp +++ b/src/openrct2/object/ObjectFactory.cpp @@ -211,6 +211,10 @@ namespace ObjectFactory { return OBJECT_TYPE_RIDE; } + else if (s == "footpath") + { + return OBJECT_TYPE_PATHS; + } else if (s == "park_entrance") { return OBJECT_TYPE_PARK_ENTRANCE; diff --git a/src/openrct2/object/ObjectJsonHelpers.cpp b/src/openrct2/object/ObjectJsonHelpers.cpp index 21dc30e661..81aa1f87df 100644 --- a/src/openrct2/object/ObjectJsonHelpers.cpp +++ b/src/openrct2/object/ObjectJsonHelpers.cpp @@ -28,6 +28,13 @@ using namespace OpenRCT2; namespace ObjectJsonHelpers { + std::string GetString(const json_t * value) + { + return json_is_string(value) ? + std::string(json_string_value(value)) : + std::string(); + } + std::vector GetJsonStringArray(const json_t * arr) { std::vector result; diff --git a/src/openrct2/object/ObjectJsonHelpers.h b/src/openrct2/object/ObjectJsonHelpers.h index b5565d5709..bcfc2eab3d 100644 --- a/src/openrct2/object/ObjectJsonHelpers.h +++ b/src/openrct2/object/ObjectJsonHelpers.h @@ -25,6 +25,7 @@ namespace ObjectJsonHelpers { + std::string GetString(const json_t * value); std::vector GetJsonStringArray(const json_t * arr); void LoadImages(const json_t * root, ImageTable &imageTable); }; From e8b28965cc14bd1b71a9c2adb0137565b9b2d8f2 Mon Sep 17 00:00:00 2001 From: Michael Steenbeek Date: Sat, 9 Dec 2017 16:23:10 +0100 Subject: [PATCH 19/93] Fix extracting ranges from object .DATs --- src/openrct2/object/ObjectJsonHelpers.cpp | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/src/openrct2/object/ObjectJsonHelpers.cpp b/src/openrct2/object/ObjectJsonHelpers.cpp index 81aa1f87df..e709e274a1 100644 --- a/src/openrct2/object/ObjectJsonHelpers.cpp +++ b/src/openrct2/object/ObjectJsonHelpers.cpp @@ -23,6 +23,7 @@ #include "Object.h" #include "ObjectFactory.h" #include "ObjectJsonHelpers.h" +#include "../core/Math.hpp" using namespace OpenRCT2; @@ -57,7 +58,7 @@ namespace ObjectJsonHelpers static std::vector ParseRange(std::string s) { // Currently only supports [###] or [###..###] - std::vector result; + std::vector result = { }; if (s.length() >= 3 && s[0] == '[' && s[s.length() - 1] == ']') { s = s.substr(1, s.length() - 2); @@ -89,7 +90,7 @@ namespace ObjectJsonHelpers return result; } - static std::vector LoadObjectImages(const std::string &name) + static std::vector LoadObjectImages(const std::string &name, uint32 start, uint32 end) { std::vector result; const auto env = GetContext()->GetPlatformEnvironment(); @@ -99,7 +100,7 @@ namespace ObjectJsonHelpers auto imgTable = static_cast(obj)->GetImageTable(); auto numImages = imgTable->GetCount(); auto images = imgTable->GetImages(); - for (uint32 i = 0; i < numImages; i++) + for (uint32 i = start; i < Math::Min(numImages, end); i++) { auto g1 = images[i]; auto length = g1_calculate_data_size(&g1); @@ -139,13 +140,22 @@ namespace ObjectJsonHelpers { auto name = s.substr(14); auto rangeStart = name.find('['); - auto range = std::vector({ 0 }); + auto imgStart = 0; + auto imgEnd = INT16_MAX; + //auto range = std::vector({ 0 }); if (rangeStart != std::string::npos) { - range = ParseRange(name.substr(rangeStart)); + auto rangeString = name.substr(rangeStart); + auto range = ParseRange(name.substr(rangeStart)); name = name.substr(0, rangeStart); + + if (range.size() > 0) + { + imgStart = range.front(); + imgEnd = range.back(); + } } - return LoadObjectImages(name); + return LoadObjectImages(name, imgStart, imgEnd); } return result; } From d56f1445f8018a56fcc8151ef5a038b727ce95bc Mon Sep 17 00:00:00 2001 From: Ted John Date: Sun, 10 Dec 2017 17:42:39 +0000 Subject: [PATCH 20/93] Add JSON loading for footpath items --- src/openrct2/object/FootpathItemObject.cpp | 108 ++++++++++++++++++++- src/openrct2/object/FootpathItemObject.h | 1 + src/openrct2/object/FootpathObject.cpp | 6 +- src/openrct2/object/ObjectFactory.cpp | 16 +-- src/openrct2/object/ObjectJsonHelpers.cpp | 8 ++ src/openrct2/object/ObjectJsonHelpers.h | 1 + 6 files changed, 123 insertions(+), 17 deletions(-) diff --git a/src/openrct2/object/FootpathItemObject.cpp b/src/openrct2/object/FootpathItemObject.cpp index bb3f6ec528..0d72d79d56 100644 --- a/src/openrct2/object/FootpathItemObject.cpp +++ b/src/openrct2/object/FootpathItemObject.cpp @@ -14,13 +14,15 @@ *****************************************************************************/ #pragma endregion +#include #include "../core/IStream.hpp" -#include "FootpathItemObject.h" - #include "../drawing/Drawing.h" +#include "../interface/Cursors.h" #include "../localisation/Localisation.h" #include "../object/Object.h" #include "ObjectList.h" +#include "FootpathItemObject.h" +#include "ObjectJsonHelpers.h" void FootpathItemObject::ReadLegacy(IReadObjectContext * context, IStream * stream) { @@ -84,3 +86,105 @@ void FootpathItemObject::DrawPreview(rct_drawpixelinfo * dpi, sint32 width, sint sint32 y = height / 2; gfx_draw_sprite(dpi, _legacyType.image, x - 22, y - 24, 0); } + +static uint8 ParseDrawType(const std::string &s) +{ + if (s == "lamp") return PATH_BIT_DRAW_TYPE_LIGHTS; + if (s == "bin") return PATH_BIT_DRAW_TYPE_BINS; + if (s == "bench") return PATH_BIT_DRAW_TYPE_BENCHES; + if (s == "fountain") return PATH_BIT_DRAW_TYPE_JUMPING_FOUNTAINS; + return PATH_BIT_DRAW_TYPE_LIGHTS; +} + +static uint8 ParseCursor(const std::string &s) +{ + static const std::unordered_map LookupTable + { + { "CURSOR_BLANK", CURSOR_BLANK }, + { "CURSOR_UP_ARROW", CURSOR_UP_ARROW }, + { "CURSOR_UP_DOWN_ARROW", CURSOR_UP_DOWN_ARROW }, + { "CURSOR_HAND_POINT", CURSOR_HAND_POINT }, + { "CURSOR_ZZZ", CURSOR_ZZZ }, + { "CURSOR_DIAGONAL_ARROWS", CURSOR_DIAGONAL_ARROWS }, + { "CURSOR_PICKER", CURSOR_PICKER }, + { "CURSOR_TREE_DOWN", CURSOR_TREE_DOWN }, + { "CURSOR_FOUNTAIN_DOWN", CURSOR_FOUNTAIN_DOWN }, + { "CURSOR_STATUE_DOWN", CURSOR_STATUE_DOWN }, + { "CURSOR_BENCH_DOWN", CURSOR_BENCH_DOWN }, + { "CURSOR_CROSS_HAIR", CURSOR_CROSS_HAIR }, + { "CURSOR_BIN_DOWN", CURSOR_BIN_DOWN }, + { "CURSOR_LAMPPOST_DOWN", CURSOR_LAMPPOST_DOWN }, + { "CURSOR_FENCE_DOWN", CURSOR_FENCE_DOWN }, + { "CURSOR_FLOWER_DOWN", CURSOR_FLOWER_DOWN }, + { "CURSOR_PATH_DOWN", CURSOR_PATH_DOWN }, + { "CURSOR_DIG_DOWN", CURSOR_DIG_DOWN }, + { "CURSOR_WATER_DOWN", CURSOR_WATER_DOWN }, + { "CURSOR_HOUSE_DOWN", CURSOR_HOUSE_DOWN }, + { "CURSOR_VOLCANO_DOWN", CURSOR_VOLCANO_DOWN }, + { "CURSOR_WALK_DOWN", CURSOR_WALK_DOWN }, + { "CURSOR_PAINT_DOWN", CURSOR_PAINT_DOWN }, + { "CURSOR_ENTRANCE_DOWN", CURSOR_ENTRANCE_DOWN }, + { "CURSOR_HAND_OPEN", CURSOR_HAND_OPEN }, + { "CURSOR_HAND_CLOSED", CURSOR_HAND_CLOSED }, + {"CURSOR_ARROW", CURSOR_ARROW }, + }; + + auto result = LookupTable.find(s); + return (result != LookupTable.end()) ? + result->second : + CURSOR_ARROW; +} + +void FootpathItemObject::ReadJson(IReadObjectContext * context, const json_t * root) +{ + // Strings + auto stringTable = GetStringTable(); + auto jsonStrings = json_object_get(root, "strings"); + auto jsonName = json_object_get(jsonStrings, "name"); + stringTable->SetString(0, 0, json_string_value(json_object_get(jsonName, "en-GB"))); + + auto properties = json_object_get(root, "properties"); + _legacyType.path_bit.draw_type = ParseDrawType(ObjectJsonHelpers::GetString(json_object_get(properties, "renderAs"))); + _legacyType.path_bit.tool_id = ParseCursor(ObjectJsonHelpers::GetString(json_object_get(properties, "cursor"))); + _legacyType.path_bit.price = json_integer_value(json_object_get(properties, "price")); + + auto scg = ObjectJsonHelpers::GetString(json_object_get(properties, "sceneryGroup")); + if (!scg.empty()) + { + rct_object_entry sgEntry = { 0 }; + strncpy(sgEntry.name, scg.c_str(), 8); + SetPrimarySceneryGroup(&sgEntry); + } + + // Flags + struct Item + { + const char * Name; + uint16 Flag; + }; + Item FlagDefs[] = + { + { "isBin", PATH_BIT_FLAG_IS_BIN }, + { "isBench", PATH_BIT_FLAG_IS_BENCH }, + { "isBreakable", PATH_BIT_FLAG_BREAKABLE }, + { "isLamp", PATH_BIT_FLAG_LAMP }, + { "isJumpingFountainWater", PATH_BIT_FLAG_JUMPING_FOUNTAIN_WATER }, + { "isJumpingFountainSnow", PATH_BIT_FLAG_JUMPING_FOUNTAIN_SNOW }, + { "isAllowedOnQueue", PATH_BIT_FLAG_DONT_ALLOW_ON_QUEUE }, + { "isAllowedOnSlope", PATH_BIT_FLAG_DONT_ALLOW_ON_SLOPE }, + { "isTelevision", PATH_BIT_FLAG_IS_QUEUE_SCREEN }, + }; + + uint16 flags = 0; + for (const auto &def : FlagDefs) + { + if (ObjectJsonHelpers::GetBoolean(properties, def.Name)) + { + flags |= def.Flag; + } + } + _legacyType.path_bit.flags = flags; + + auto imageTable = GetImageTable(); + ObjectJsonHelpers::LoadImages(root, *imageTable); +} diff --git a/src/openrct2/object/FootpathItemObject.h b/src/openrct2/object/FootpathItemObject.h index 14d2c7fefc..d2099b569d 100644 --- a/src/openrct2/object/FootpathItemObject.h +++ b/src/openrct2/object/FootpathItemObject.h @@ -31,6 +31,7 @@ public: void * GetLegacyData() override { return &_legacyType; } void ReadLegacy(IReadObjectContext * context, IStream * stream) override; + void ReadJson(IReadObjectContext * context, const json_t * root) override; void Load() override; void Unload() override; diff --git a/src/openrct2/object/FootpathObject.cpp b/src/openrct2/object/FootpathObject.cpp index f817f2ab51..992a0249cd 100644 --- a/src/openrct2/object/FootpathObject.cpp +++ b/src/openrct2/object/FootpathObject.cpp @@ -84,15 +84,15 @@ void FootpathObject::ReadJson(IReadObjectContext * context, const json_t * root) // Flags _legacyType.flags = 0; - if (json_boolean_value(json_object_get(properties, "hasSupportImages"))) + if (ObjectJsonHelpers::GetBoolean(properties, "hasSupportImages")) { _legacyType.flags |= FOOTPATH_ENTRY_FLAG_HAS_SUPPORT_BASE_SPRITE; } - if (json_boolean_value(json_object_get(properties, "hasElevatedPathImages"))) + if (ObjectJsonHelpers::GetBoolean(properties, "hasElevatedPathImages")) { _legacyType.flags |= FOOTPATH_ENTRY_FLAG_HAS_PATH_BASE_SPRITE; } - if (json_boolean_value(json_object_get(properties, "editorOnly"))) + if (ObjectJsonHelpers::GetBoolean(properties, "editorOnly")) { _legacyType.flags |= FOOTPATH_ENTRY_FLAG_SHOW_ONLY_IN_SCENARIO_EDITOR; } diff --git a/src/openrct2/object/ObjectFactory.cpp b/src/openrct2/object/ObjectFactory.cpp index 6fefc0840d..e7494502c6 100644 --- a/src/openrct2/object/ObjectFactory.cpp +++ b/src/openrct2/object/ObjectFactory.cpp @@ -207,18 +207,10 @@ namespace ObjectFactory static uint8 ParseObjectType(const std::string &s) { - if (s == "ride") - { - return OBJECT_TYPE_RIDE; - } - else if (s == "footpath") - { - return OBJECT_TYPE_PATHS; - } - else if (s == "park_entrance") - { - return OBJECT_TYPE_PARK_ENTRANCE; - } + if (s == "ride") return OBJECT_TYPE_RIDE; + if (s == "footpath") return OBJECT_TYPE_PATHS; + if (s == "footpath_item") return OBJECT_TYPE_PATH_BITS; + if (s == "park_entrance") return OBJECT_TYPE_PARK_ENTRANCE; return 0xFF; } diff --git a/src/openrct2/object/ObjectJsonHelpers.cpp b/src/openrct2/object/ObjectJsonHelpers.cpp index e709e274a1..51cf3bf325 100644 --- a/src/openrct2/object/ObjectJsonHelpers.cpp +++ b/src/openrct2/object/ObjectJsonHelpers.cpp @@ -29,6 +29,14 @@ using namespace OpenRCT2; namespace ObjectJsonHelpers { + bool GetBoolean(const json_t * obj, const std::string &name, bool defaultValue) + { + auto value = json_object_get(obj, name.c_str()); + return json_is_boolean(value) ? + json_boolean_value(value) : + defaultValue; + } + std::string GetString(const json_t * value) { return json_is_string(value) ? diff --git a/src/openrct2/object/ObjectJsonHelpers.h b/src/openrct2/object/ObjectJsonHelpers.h index bcfc2eab3d..76f8f20077 100644 --- a/src/openrct2/object/ObjectJsonHelpers.h +++ b/src/openrct2/object/ObjectJsonHelpers.h @@ -25,6 +25,7 @@ namespace ObjectJsonHelpers { + bool GetBoolean(const json_t * obj, const std::string &name, bool defaultValue = false); std::string GetString(const json_t * value); std::vector GetJsonStringArray(const json_t * arr); void LoadImages(const json_t * root, ImageTable &imageTable); From 900bc48efaead7a8b3b1fc38525e5530ffe7a603 Mon Sep 17 00:00:00 2001 From: Ted John Date: Mon, 11 Dec 2017 12:30:08 +0000 Subject: [PATCH 21/93] Write common JSON string loader --- src/openrct2/localisation/Language.cpp | 14 ++++++++ src/openrct2/localisation/Language.h | 1 + src/openrct2/object/EntranceObject.cpp | 10 ++---- src/openrct2/object/FootpathItemObject.cpp | 10 ++---- src/openrct2/object/FootpathObject.cpp | 10 ++---- src/openrct2/object/Object.h | 5 +-- src/openrct2/object/ObjectJsonHelpers.cpp | 39 +++++++++++++++++++++- src/openrct2/object/ObjectJsonHelpers.h | 2 ++ src/openrct2/object/RideObject.cpp | 18 ++-------- src/openrct2/object/StringTable.cpp | 2 +- 10 files changed, 68 insertions(+), 43 deletions(-) diff --git a/src/openrct2/localisation/Language.cpp b/src/openrct2/localisation/Language.cpp index d1ab538d8f..caba5e3289 100644 --- a/src/openrct2/localisation/Language.cpp +++ b/src/openrct2/localisation/Language.cpp @@ -83,6 +83,20 @@ void utf8_remove_format_codes(utf8 * text, bool allowcolours) *dstCh = 0; } +uint8 language_get_id_from_locale(const char * locale) +{ + uint8 i = 0; + for (const auto &langDesc : LanguagesDescriptors) + { + if (String::Equals(locale, langDesc.locale)) + { + return i; + } + i++; + } + return LANGUAGE_UNDEFINED; +} + const char * language_get_string(rct_string_id id) { const char * result = nullptr; diff --git a/src/openrct2/localisation/Language.h b/src/openrct2/localisation/Language.h index 9bccd0be60..2188080e0b 100644 --- a/src/openrct2/localisation/Language.h +++ b/src/openrct2/localisation/Language.h @@ -94,6 +94,7 @@ extern const utf8 BlackLeftArrowString[]; extern const utf8 BlackRightArrowString[]; extern const utf8 CheckBoxMarkString[]; +uint8 language_get_id_from_locale(const char * locale); const char *language_get_string(rct_string_id id); bool language_open(sint32 id); void language_close_all(); diff --git a/src/openrct2/object/EntranceObject.cpp b/src/openrct2/object/EntranceObject.cpp index 814a34fedf..7f84072a16 100644 --- a/src/openrct2/object/EntranceObject.cpp +++ b/src/openrct2/object/EntranceObject.cpp @@ -68,16 +68,10 @@ void EntranceObject::DrawPreview(rct_drawpixelinfo * dpi, sint32 width, sint32 h void EntranceObject::ReadJson(IReadObjectContext * context, const json_t * root) { - // Strings - auto stringTable = GetStringTable(); - auto jsonStrings = json_object_get(root, "strings"); - auto jsonName = json_object_get(jsonStrings, "name"); - stringTable->SetString(0, 0, json_string_value(json_object_get(jsonName, "en-GB"))); - auto properties = json_object_get(root, "properties"); _legacyType.scrolling_mode = json_integer_value(json_object_get(properties, "scrollingMode")); _legacyType.text_height = json_integer_value(json_object_get(properties, "textHeight")); - auto imageTable = GetImageTable(); - ObjectJsonHelpers::LoadImages(root, *imageTable); + ObjectJsonHelpers::LoadStrings(root, *GetStringTable()); + ObjectJsonHelpers::LoadImages(root, *GetImageTable()); } diff --git a/src/openrct2/object/FootpathItemObject.cpp b/src/openrct2/object/FootpathItemObject.cpp index 0d72d79d56..0586a6354c 100644 --- a/src/openrct2/object/FootpathItemObject.cpp +++ b/src/openrct2/object/FootpathItemObject.cpp @@ -137,12 +137,6 @@ static uint8 ParseCursor(const std::string &s) void FootpathItemObject::ReadJson(IReadObjectContext * context, const json_t * root) { - // Strings - auto stringTable = GetStringTable(); - auto jsonStrings = json_object_get(root, "strings"); - auto jsonName = json_object_get(jsonStrings, "name"); - stringTable->SetString(0, 0, json_string_value(json_object_get(jsonName, "en-GB"))); - auto properties = json_object_get(root, "properties"); _legacyType.path_bit.draw_type = ParseDrawType(ObjectJsonHelpers::GetString(json_object_get(properties, "renderAs"))); _legacyType.path_bit.tool_id = ParseCursor(ObjectJsonHelpers::GetString(json_object_get(properties, "cursor"))); @@ -185,6 +179,6 @@ void FootpathItemObject::ReadJson(IReadObjectContext * context, const json_t * r } _legacyType.path_bit.flags = flags; - auto imageTable = GetImageTable(); - ObjectJsonHelpers::LoadImages(root, *imageTable); + ObjectJsonHelpers::LoadStrings(root, *GetStringTable()); + ObjectJsonHelpers::LoadImages(root, *GetImageTable()); } diff --git a/src/openrct2/object/FootpathObject.cpp b/src/openrct2/object/FootpathObject.cpp index 992a0249cd..4d5befd9b7 100644 --- a/src/openrct2/object/FootpathObject.cpp +++ b/src/openrct2/object/FootpathObject.cpp @@ -72,12 +72,6 @@ static uint8 ParseSupportType(const std::string &s) void FootpathObject::ReadJson(IReadObjectContext * context, const json_t * root) { - // Strings - auto stringTable = GetStringTable(); - auto jsonStrings = json_object_get(root, "strings"); - auto jsonName = json_object_get(jsonStrings, "name"); - stringTable->SetString(0, 0, json_string_value(json_object_get(jsonName, "en-GB"))); - auto properties = json_object_get(root, "properties"); _legacyType.support_type = ParseSupportType(ObjectJsonHelpers::GetString(json_object_get(properties, "supportType"))); _legacyType.scrolling_mode = json_integer_value(json_object_get(properties, "scrollingMode")); @@ -97,6 +91,6 @@ void FootpathObject::ReadJson(IReadObjectContext * context, const json_t * root) _legacyType.flags |= FOOTPATH_ENTRY_FLAG_SHOW_ONLY_IN_SCENARIO_EDITOR; } - auto imageTable = GetImageTable(); - ObjectJsonHelpers::LoadImages(root, *imageTable); + ObjectJsonHelpers::LoadStrings(root, *GetStringTable()); + ObjectJsonHelpers::LoadImages(root, *GetImageTable()); } diff --git a/src/openrct2/object/Object.h b/src/openrct2/object/Object.h index c00101254e..fb437c56e0 100644 --- a/src/openrct2/object/Object.h +++ b/src/openrct2/object/Object.h @@ -111,9 +111,10 @@ struct rct_object_filters { assert_struct_size(rct_object_filters, 3); #pragma pack(pop) -enum OBJ_STRING_ID +enum OBJ_STRING_ID : uint8 { - OBJ_STRING_ID_NAME, + OBJ_STRING_ID_UNKNOWN = 255, + OBJ_STRING_ID_NAME = 0, OBJ_STRING_ID_DESCRIPTION, OBJ_STRING_ID_SCENARIO_NAME = 0, OBJ_STRING_ID_PARK_NAME = 1, diff --git a/src/openrct2/object/ObjectJsonHelpers.cpp b/src/openrct2/object/ObjectJsonHelpers.cpp index 51cf3bf325..286cb325e1 100644 --- a/src/openrct2/object/ObjectJsonHelpers.cpp +++ b/src/openrct2/object/ObjectJsonHelpers.cpp @@ -14,16 +14,19 @@ *****************************************************************************/ #pragma endregion +#pragma warning(disable : 4706) // assignment within conditional expression + #include "../Context.h" +#include "../core/Math.hpp" #include "../core/Memory.hpp" #include "../core/Path.hpp" #include "../core/String.hpp" +#include "../localisation/language.h" #include "../PlatformEnvironment.h" #include "../sprites.h" #include "Object.h" #include "ObjectFactory.h" #include "ObjectJsonHelpers.h" -#include "../core/Math.hpp" using namespace OpenRCT2; @@ -168,6 +171,40 @@ namespace ObjectJsonHelpers return result; } + static uint8 ParseStringId(const std::string &s) + { + if (s == "name") return OBJ_STRING_ID_NAME; + if (s == "description") return OBJ_STRING_ID_DESCRIPTION; + if (s == "capacity") return OBJ_STRING_ID_CAPACITY; + if (s == "vehicleName") return OBJ_STRING_ID_VEHICLE_NAME; + return OBJ_STRING_ID_UNKNOWN; + } + + void LoadStrings(const json_t * root, StringTable &stringTable) + { + auto jsonStrings = json_object_get(root, "strings"); + const char * key; + json_t * jlanguages; + json_object_foreach(jsonStrings, key, jlanguages) + { + auto stringId = ParseStringId(key); + if (stringId != OBJ_STRING_ID_UNKNOWN) + { + const char * locale; + json_t * jstring; + json_object_foreach(jlanguages, locale, jstring) + { + auto langId = language_get_id_from_locale(locale); + if (langId != LANGUAGE_UNDEFINED) + { + auto string = json_string_value(jstring); + stringTable.SetString(stringId, langId, string); + } + } + } + } + } + void LoadImages(const json_t * root, ImageTable &imageTable) { auto jsonImages = json_object_get(root, "images"); diff --git a/src/openrct2/object/ObjectJsonHelpers.h b/src/openrct2/object/ObjectJsonHelpers.h index 76f8f20077..866fada431 100644 --- a/src/openrct2/object/ObjectJsonHelpers.h +++ b/src/openrct2/object/ObjectJsonHelpers.h @@ -22,11 +22,13 @@ #include "../core/Json.hpp" #include "../drawing/drawing.h" #include "ImageTable.h" +#include "StringTable.h" namespace ObjectJsonHelpers { bool GetBoolean(const json_t * obj, const std::string &name, bool defaultValue = false); std::string GetString(const json_t * value); std::vector GetJsonStringArray(const json_t * arr); + void LoadStrings(const json_t * root, StringTable &stringTable); void LoadImages(const json_t * root, ImageTable &imageTable); }; diff --git a/src/openrct2/object/RideObject.cpp b/src/openrct2/object/RideObject.cpp index 58aecd13c8..7ca4546567 100644 --- a/src/openrct2/object/RideObject.cpp +++ b/src/openrct2/object/RideObject.cpp @@ -726,22 +726,10 @@ void RideObject::ReadJson(IReadObjectContext * context, const json_t * root) _legacyType.shop_item_secondary = ParseShopItem(rideSells[1]); } - _legacyType.flags |= RIDE_ENTRY_FLAG_SEPARATE_RIDE; - - auto stringTable = GetStringTable(); - auto jsonStrings = json_object_get(root, "strings"); - auto jsonName = json_object_get(jsonStrings, "name"); - auto jsonDescription = json_object_get(jsonStrings, "description"); - - stringTable->SetString(0, 0, json_string_value(json_object_get(jsonName, "en-GB"))); - stringTable->SetString(1, 0, json_string_value(json_object_get(jsonDescription, "en-GB"))); - stringTable->SetString(2, 0, "Capacity"); - stringTable->SetString(3, 0, "Vehicle"); - - auto imageTable = GetImageTable(); - ObjectJsonHelpers::LoadImages(root, *imageTable); - rct_ride_entry_vehicle * vehicle0 = &_legacyType.vehicles[0]; vehicle0->sprite_flags |= VEHICLE_SPRITE_FLAG_FLAT; vehicle0->base_image_id = 0; + + ObjectJsonHelpers::LoadStrings(root, *GetStringTable()); + ObjectJsonHelpers::LoadImages(root, *GetImageTable()); } diff --git a/src/openrct2/object/StringTable.cpp b/src/openrct2/object/StringTable.cpp index 5b7ee08dd3..521124a7ae 100644 --- a/src/openrct2/object/StringTable.cpp +++ b/src/openrct2/object/StringTable.cpp @@ -97,7 +97,7 @@ std::string StringTable::GetString(uint8 id) const return string.Text; } } - return nullptr; + return std::string(); } void StringTable::SetString(uint8 id, uint8 language, const std::string &text) From c3f075d18ca1586698fe045824f2aaaf10e0144b Mon Sep 17 00:00:00 2001 From: Ted John Date: Mon, 11 Dec 2017 12:44:37 +0000 Subject: [PATCH 22/93] Write helper method for parsing flags --- src/openrct2/object/FootpathItemObject.cpp | 21 ++------------------- src/openrct2/object/FootpathObject.cpp | 17 ++++------------- src/openrct2/object/ObjectJsonHelpers.h | 16 ++++++++++++++++ 3 files changed, 22 insertions(+), 32 deletions(-) diff --git a/src/openrct2/object/FootpathItemObject.cpp b/src/openrct2/object/FootpathItemObject.cpp index 0586a6354c..8d5b0e87eb 100644 --- a/src/openrct2/object/FootpathItemObject.cpp +++ b/src/openrct2/object/FootpathItemObject.cpp @@ -151,13 +151,7 @@ void FootpathItemObject::ReadJson(IReadObjectContext * context, const json_t * r } // Flags - struct Item - { - const char * Name; - uint16 Flag; - }; - Item FlagDefs[] = - { + _legacyType.path_bit.flags = ObjectJsonHelpers::GetFlags(properties, { { "isBin", PATH_BIT_FLAG_IS_BIN }, { "isBench", PATH_BIT_FLAG_IS_BENCH }, { "isBreakable", PATH_BIT_FLAG_BREAKABLE }, @@ -166,18 +160,7 @@ void FootpathItemObject::ReadJson(IReadObjectContext * context, const json_t * r { "isJumpingFountainSnow", PATH_BIT_FLAG_JUMPING_FOUNTAIN_SNOW }, { "isAllowedOnQueue", PATH_BIT_FLAG_DONT_ALLOW_ON_QUEUE }, { "isAllowedOnSlope", PATH_BIT_FLAG_DONT_ALLOW_ON_SLOPE }, - { "isTelevision", PATH_BIT_FLAG_IS_QUEUE_SCREEN }, - }; - - uint16 flags = 0; - for (const auto &def : FlagDefs) - { - if (ObjectJsonHelpers::GetBoolean(properties, def.Name)) - { - flags |= def.Flag; - } - } - _legacyType.path_bit.flags = flags; + { "isTelevision", PATH_BIT_FLAG_IS_QUEUE_SCREEN }}); ObjectJsonHelpers::LoadStrings(root, *GetStringTable()); ObjectJsonHelpers::LoadImages(root, *GetImageTable()); diff --git a/src/openrct2/object/FootpathObject.cpp b/src/openrct2/object/FootpathObject.cpp index 4d5befd9b7..da8e1ec398 100644 --- a/src/openrct2/object/FootpathObject.cpp +++ b/src/openrct2/object/FootpathObject.cpp @@ -77,19 +77,10 @@ void FootpathObject::ReadJson(IReadObjectContext * context, const json_t * root) _legacyType.scrolling_mode = json_integer_value(json_object_get(properties, "scrollingMode")); // Flags - _legacyType.flags = 0; - if (ObjectJsonHelpers::GetBoolean(properties, "hasSupportImages")) - { - _legacyType.flags |= FOOTPATH_ENTRY_FLAG_HAS_SUPPORT_BASE_SPRITE; - } - if (ObjectJsonHelpers::GetBoolean(properties, "hasElevatedPathImages")) - { - _legacyType.flags |= FOOTPATH_ENTRY_FLAG_HAS_PATH_BASE_SPRITE; - } - if (ObjectJsonHelpers::GetBoolean(properties, "editorOnly")) - { - _legacyType.flags |= FOOTPATH_ENTRY_FLAG_SHOW_ONLY_IN_SCENARIO_EDITOR; - } + _legacyType.flags = ObjectJsonHelpers::GetFlags(properties, { + { "hasSupportImages", FOOTPATH_ENTRY_FLAG_HAS_SUPPORT_BASE_SPRITE }, + { "hasElevatedPathImages", FOOTPATH_ENTRY_FLAG_HAS_PATH_BASE_SPRITE }, + { "editorOnly", FOOTPATH_ENTRY_FLAG_SHOW_ONLY_IN_SCENARIO_EDITOR } }); ObjectJsonHelpers::LoadStrings(root, *GetStringTable()); ObjectJsonHelpers::LoadImages(root, *GetImageTable()); diff --git a/src/openrct2/object/ObjectJsonHelpers.h b/src/openrct2/object/ObjectJsonHelpers.h index 866fada431..c2edea2741 100644 --- a/src/openrct2/object/ObjectJsonHelpers.h +++ b/src/openrct2/object/ObjectJsonHelpers.h @@ -16,7 +16,9 @@ #pragma once +#include #include +#include #include #include "../common.h" #include "../core/Json.hpp" @@ -31,4 +33,18 @@ namespace ObjectJsonHelpers std::vector GetJsonStringArray(const json_t * arr); void LoadStrings(const json_t * root, StringTable &stringTable); void LoadImages(const json_t * root, ImageTable &imageTable); + + template + T GetFlags(const json_t * obj, std::initializer_list> list) + { + T flags = 0; + for (const auto &item : list) + { + if (GetBoolean(obj, item.first)) + { + flags |= item.second; + } + } + return flags; + } }; From ec446ac9d6ce57542722263d3d1ac6e4e3dec349 Mon Sep 17 00:00:00 2001 From: Ted John Date: Mon, 11 Dec 2017 13:06:59 +0000 Subject: [PATCH 23/93] Return image and string table by reference --- src/openrct2/object/BannerObject.cpp | 10 +++++----- src/openrct2/object/EntranceObject.cpp | 14 +++++++------- src/openrct2/object/FootpathItemObject.cpp | 14 +++++++------- src/openrct2/object/FootpathObject.cpp | 14 +++++++------- src/openrct2/object/ImageTable.h | 3 +++ src/openrct2/object/LargeSceneryObject.cpp | 10 +++++----- src/openrct2/object/Object.cpp | 2 +- src/openrct2/object/Object.h | 19 ++++--------------- src/openrct2/object/ObjectJsonHelpers.cpp | 6 +++--- src/openrct2/object/RideObject.cpp | 18 +++++++++--------- src/openrct2/object/SceneryGroupObject.cpp | 6 +++--- src/openrct2/object/SmallSceneryObject.cpp | 10 +++++----- src/openrct2/object/StexObject.cpp | 14 +++++++------- src/openrct2/object/StringTable.h | 21 +++++++++++++++++++-- src/openrct2/object/WallObject.cpp | 10 +++++----- src/openrct2/object/WaterObject.cpp | 10 +++++----- 16 files changed, 95 insertions(+), 86 deletions(-) diff --git a/src/openrct2/object/BannerObject.cpp b/src/openrct2/object/BannerObject.cpp index 146fa47adb..a70cb659f3 100644 --- a/src/openrct2/object/BannerObject.cpp +++ b/src/openrct2/object/BannerObject.cpp @@ -31,12 +31,12 @@ void BannerObject::ReadLegacy(IReadObjectContext * context, IStream * stream) _legacyType.banner.scenery_tab_id = stream->ReadValue(); stream->Seek(1, STREAM_SEEK_CURRENT); - GetStringTable()->Read(context, stream, OBJ_STRING_ID_NAME); + GetStringTable().Read(context, stream, OBJ_STRING_ID_NAME); rct_object_entry sgEntry = stream->ReadValue(); SetPrimarySceneryGroup(&sgEntry); - GetImageTable()->Read(context, stream); + GetImageTable().Read(context, stream); // Validate properties if (_legacyType.large_scenery.price <= 0) @@ -61,15 +61,15 @@ void BannerObject::ReadLegacy(IReadObjectContext * context, IStream * stream) void BannerObject::Load() { - GetStringTable()->Sort(); + GetStringTable().Sort(); _legacyType.name = language_allocate_object_string(GetName()); - _legacyType.image = gfx_object_allocate_images(GetImageTable()->GetImages(), GetImageTable()->GetCount()); + _legacyType.image = gfx_object_allocate_images(GetImageTable().GetImages(), GetImageTable().GetCount()); } void BannerObject::Unload() { language_free_object_string(_legacyType.name); - gfx_object_free_images(_legacyType.image, GetImageTable()->GetCount()); + gfx_object_free_images(_legacyType.image, GetImageTable().GetCount()); _legacyType.name = 0; _legacyType.image = 0; diff --git a/src/openrct2/object/EntranceObject.cpp b/src/openrct2/object/EntranceObject.cpp index 7f84072a16..c49b213b93 100644 --- a/src/openrct2/object/EntranceObject.cpp +++ b/src/openrct2/object/EntranceObject.cpp @@ -27,8 +27,8 @@ void EntranceObject::ReadLegacy(IReadObjectContext * context, IStream * stream) _legacyType.scrolling_mode = stream->ReadValue(); _legacyType.text_height = stream->ReadValue(); - GetStringTable()->Read(context, stream, OBJ_STRING_ID_NAME); - GetImageTable()->Read(context, stream); + GetStringTable().Read(context, stream, OBJ_STRING_ID_NAME); + GetImageTable().Read(context, stream); // Fix issue #1705: The Medieval entrance from Time Twister has a straight banner, // but scrolls its text as if it a curved one. @@ -41,15 +41,15 @@ void EntranceObject::ReadLegacy(IReadObjectContext * context, IStream * stream) void EntranceObject::Load() { - GetStringTable()->Sort(); + GetStringTable().Sort(); _legacyType.string_idx = language_allocate_object_string(GetName()); - _legacyType.image_id = gfx_object_allocate_images(GetImageTable()->GetImages(), GetImageTable()->GetCount()); + _legacyType.image_id = gfx_object_allocate_images(GetImageTable().GetImages(), GetImageTable().GetCount()); } void EntranceObject::Unload() { language_free_object_string(_legacyType.string_idx); - gfx_object_free_images(_legacyType.image_id, GetImageTable()->GetCount()); + gfx_object_free_images(_legacyType.image_id, GetImageTable().GetCount()); _legacyType.string_idx = 0; _legacyType.image_id = 0; @@ -72,6 +72,6 @@ void EntranceObject::ReadJson(IReadObjectContext * context, const json_t * root) _legacyType.scrolling_mode = json_integer_value(json_object_get(properties, "scrollingMode")); _legacyType.text_height = json_integer_value(json_object_get(properties, "textHeight")); - ObjectJsonHelpers::LoadStrings(root, *GetStringTable()); - ObjectJsonHelpers::LoadImages(root, *GetImageTable()); + ObjectJsonHelpers::LoadStrings(root, GetStringTable()); + ObjectJsonHelpers::LoadImages(root, GetImageTable()); } diff --git a/src/openrct2/object/FootpathItemObject.cpp b/src/openrct2/object/FootpathItemObject.cpp index 8d5b0e87eb..e864d85cbb 100644 --- a/src/openrct2/object/FootpathItemObject.cpp +++ b/src/openrct2/object/FootpathItemObject.cpp @@ -34,12 +34,12 @@ void FootpathItemObject::ReadLegacy(IReadObjectContext * context, IStream * stre _legacyType.path_bit.scenery_tab_id = stream->ReadValue(); stream->Seek(1, STREAM_SEEK_CURRENT); - GetStringTable()->Read(context, stream, OBJ_STRING_ID_NAME); + GetStringTable().Read(context, stream, OBJ_STRING_ID_NAME); rct_object_entry sgEntry = stream->ReadValue(); SetPrimarySceneryGroup(&sgEntry); - GetImageTable()->Read(context, stream); + GetImageTable().Read(context, stream); // Validate properties if (_legacyType.large_scenery.price <= 0) @@ -64,9 +64,9 @@ void FootpathItemObject::ReadLegacy(IReadObjectContext * context, IStream * stre void FootpathItemObject::Load() { - GetStringTable()->Sort(); + GetStringTable().Sort(); _legacyType.name = language_allocate_object_string(GetName()); - _legacyType.image = gfx_object_allocate_images(GetImageTable()->GetImages(), GetImageTable()->GetCount()); + _legacyType.image = gfx_object_allocate_images(GetImageTable().GetImages(), GetImageTable().GetCount()); _legacyType.path_bit.scenery_tab_id = 0xFF; } @@ -74,7 +74,7 @@ void FootpathItemObject::Load() void FootpathItemObject::Unload() { language_free_object_string(_legacyType.name); - gfx_object_free_images(_legacyType.image, GetImageTable()->GetCount()); + gfx_object_free_images(_legacyType.image, GetImageTable().GetCount()); _legacyType.name = 0; _legacyType.image = 0; @@ -162,6 +162,6 @@ void FootpathItemObject::ReadJson(IReadObjectContext * context, const json_t * r { "isAllowedOnSlope", PATH_BIT_FLAG_DONT_ALLOW_ON_SLOPE }, { "isTelevision", PATH_BIT_FLAG_IS_QUEUE_SCREEN }}); - ObjectJsonHelpers::LoadStrings(root, *GetStringTable()); - ObjectJsonHelpers::LoadImages(root, *GetImageTable()); + ObjectJsonHelpers::LoadStrings(root, GetStringTable()); + ObjectJsonHelpers::LoadImages(root, GetImageTable()); } diff --git a/src/openrct2/object/FootpathObject.cpp b/src/openrct2/object/FootpathObject.cpp index da8e1ec398..9595b7911d 100644 --- a/src/openrct2/object/FootpathObject.cpp +++ b/src/openrct2/object/FootpathObject.cpp @@ -29,8 +29,8 @@ void FootpathObject::ReadLegacy(IReadObjectContext * context, IStream * stream) _legacyType.scrolling_mode = stream->ReadValue(); stream->Seek(1, STREAM_SEEK_CURRENT); - GetStringTable()->Read(context, stream, OBJ_STRING_ID_NAME); - GetImageTable()->Read(context, stream); + GetStringTable().Read(context, stream, OBJ_STRING_ID_NAME); + GetImageTable().Read(context, stream); // Validate properties if (_legacyType.support_type >= FOOTPATH_ENTRY_SUPPORT_TYPE_COUNT) @@ -41,16 +41,16 @@ void FootpathObject::ReadLegacy(IReadObjectContext * context, IStream * stream) void FootpathObject::Load() { - GetStringTable()->Sort(); + GetStringTable().Sort(); _legacyType.string_idx = language_allocate_object_string(GetName()); - _legacyType.image = gfx_object_allocate_images(GetImageTable()->GetImages(), GetImageTable()->GetCount()); + _legacyType.image = gfx_object_allocate_images(GetImageTable().GetImages(), GetImageTable().GetCount()); _legacyType.bridge_image = _legacyType.image + 109; } void FootpathObject::Unload() { language_free_object_string(_legacyType.string_idx); - gfx_object_free_images(_legacyType.image, GetImageTable()->GetCount()); + gfx_object_free_images(_legacyType.image, GetImageTable().GetCount()); _legacyType.string_idx = 0; _legacyType.image = 0; @@ -82,6 +82,6 @@ void FootpathObject::ReadJson(IReadObjectContext * context, const json_t * root) { "hasElevatedPathImages", FOOTPATH_ENTRY_FLAG_HAS_PATH_BASE_SPRITE }, { "editorOnly", FOOTPATH_ENTRY_FLAG_SHOW_ONLY_IN_SCENARIO_EDITOR } }); - ObjectJsonHelpers::LoadStrings(root, *GetStringTable()); - ObjectJsonHelpers::LoadImages(root, *GetImageTable()); + ObjectJsonHelpers::LoadStrings(root, GetStringTable()); + ObjectJsonHelpers::LoadImages(root, GetImageTable()); } diff --git a/src/openrct2/object/ImageTable.h b/src/openrct2/object/ImageTable.h index c2c6c1b10a..4d90b946f4 100644 --- a/src/openrct2/object/ImageTable.h +++ b/src/openrct2/object/ImageTable.h @@ -31,6 +31,9 @@ private: std::vector _entries; public: + ImageTable() = default; + ImageTable(const ImageTable &) = delete; + ImageTable & operator=(const ImageTable &) = delete; ~ImageTable(); void Read(IReadObjectContext * context, IStream * stream); diff --git a/src/openrct2/object/LargeSceneryObject.cpp b/src/openrct2/object/LargeSceneryObject.cpp index a11698e276..6dee19c775 100644 --- a/src/openrct2/object/LargeSceneryObject.cpp +++ b/src/openrct2/object/LargeSceneryObject.cpp @@ -33,7 +33,7 @@ void LargeSceneryObject::ReadLegacy(IReadObjectContext * context, IStream * stre _legacyType.large_scenery.scrolling_mode = stream->ReadValue(); stream->Seek(4, STREAM_SEEK_CURRENT); - GetStringTable()->Read(context, stream, OBJ_STRING_ID_NAME); + GetStringTable().Read(context, stream, OBJ_STRING_ID_NAME); rct_object_entry sgEntry = stream->ReadValue(); SetPrimarySceneryGroup(&sgEntry); @@ -47,7 +47,7 @@ void LargeSceneryObject::ReadLegacy(IReadObjectContext * context, IStream * stre _tiles = ReadTiles(stream); - GetImageTable()->Read(context, stream); + GetImageTable().Read(context, stream); // Validate properties if (_legacyType.large_scenery.price <= 0) @@ -67,9 +67,9 @@ void LargeSceneryObject::ReadLegacy(IReadObjectContext * context, IStream * stre void LargeSceneryObject::Load() { - GetStringTable()->Sort(); + GetStringTable().Sort(); _legacyType.name = language_allocate_object_string(GetName()); - _baseImageId = gfx_object_allocate_images(GetImageTable()->GetImages(), GetImageTable()->GetCount()); + _baseImageId = gfx_object_allocate_images(GetImageTable().GetImages(), GetImageTable().GetCount()); _legacyType.image = _baseImageId; _legacyType.large_scenery.tiles = _tiles.data(); @@ -91,7 +91,7 @@ void LargeSceneryObject::Load() void LargeSceneryObject::Unload() { language_free_object_string(_legacyType.name); - gfx_object_free_images(_baseImageId, GetImageTable()->GetCount()); + gfx_object_free_images(_baseImageId, GetImageTable().GetCount()); _legacyType.name = 0; _legacyType.image = 0; diff --git a/src/openrct2/object/Object.cpp b/src/openrct2/object/Object.cpp index b5d301e6b6..fa83f26d0a 100644 --- a/src/openrct2/object/Object.cpp +++ b/src/openrct2/object/Object.cpp @@ -71,7 +71,7 @@ std::string Object::GetString(uint8 index) const auto sz = GetOverrideString(index); if (sz.empty()) { - sz = GetStringTable()->GetString(index); + sz = GetStringTable().GetString(index); } return sz; } diff --git a/src/openrct2/object/Object.h b/src/openrct2/object/Object.h index fb437c56e0..05e93481fb 100644 --- a/src/openrct2/object/Object.h +++ b/src/openrct2/object/Object.h @@ -111,17 +111,6 @@ struct rct_object_filters { assert_struct_size(rct_object_filters, 3); #pragma pack(pop) -enum OBJ_STRING_ID : uint8 -{ - OBJ_STRING_ID_UNKNOWN = 255, - OBJ_STRING_ID_NAME = 0, - OBJ_STRING_ID_DESCRIPTION, - OBJ_STRING_ID_SCENARIO_NAME = 0, - OBJ_STRING_ID_PARK_NAME = 1, - OBJ_STRING_ID_SCENARIO_DETAILS = 2, - OBJ_STRING_ID_CAPACITY = 2, -}; - interface IStream; struct ObjectRepositoryItem; struct rct_drawpixelinfo; @@ -148,9 +137,9 @@ private: ImageTable _imageTable; protected: - StringTable * GetStringTable() { return &_stringTable; } - const StringTable * GetStringTable() const { return &_stringTable; } - ImageTable * GetImageTable() { return &_imageTable; } + StringTable & GetStringTable() { return _stringTable; } + const StringTable & GetStringTable() const { return _stringTable; } + ImageTable & GetImageTable() { return _imageTable; } std::string GetOverrideString(uint8 index) const; std::string GetString(uint8 index) const; @@ -182,7 +171,7 @@ public: virtual void SetRepositoryItem(ObjectRepositoryItem * item) const { } - const ImageTable * GetImageTable() const { return &_imageTable; } + const ImageTable & GetImageTable() const { return _imageTable; } rct_object_entry GetScgWallsHeader(); rct_object_entry GetScgPathXHeader(); diff --git a/src/openrct2/object/ObjectJsonHelpers.cpp b/src/openrct2/object/ObjectJsonHelpers.cpp index 286cb325e1..a47bf77b4d 100644 --- a/src/openrct2/object/ObjectJsonHelpers.cpp +++ b/src/openrct2/object/ObjectJsonHelpers.cpp @@ -108,9 +108,9 @@ namespace ObjectJsonHelpers auto objectsPath = env->GetDirectoryPath(DIRBASE::RCT2, DIRID::OBJECT); auto objectPath = Path::Combine(objectsPath, name); auto obj = ObjectFactory::CreateObjectFromLegacyFile(objectPath.c_str()); - auto imgTable = static_cast(obj)->GetImageTable(); - auto numImages = imgTable->GetCount(); - auto images = imgTable->GetImages(); + auto &imgTable = static_cast(obj)->GetImageTable(); + auto numImages = imgTable.GetCount(); + auto images = imgTable.GetImages(); for (uint32 i = start; i < Math::Min(numImages, end); i++) { auto g1 = images[i]; diff --git a/src/openrct2/object/RideObject.cpp b/src/openrct2/object/RideObject.cpp index 7ca4546567..926dc1ac1d 100644 --- a/src/openrct2/object/RideObject.cpp +++ b/src/openrct2/object/RideObject.cpp @@ -78,9 +78,9 @@ void RideObject::ReadLegacy(IReadObjectContext * context, IStream * stream) _legacyType.shop_item = stream->ReadValue(); _legacyType.shop_item_secondary = stream->ReadValue(); - GetStringTable()->Read(context, stream, OBJ_STRING_ID_NAME); - GetStringTable()->Read(context, stream, OBJ_STRING_ID_DESCRIPTION); - GetStringTable()->Read(context, stream, OBJ_STRING_ID_CAPACITY); + GetStringTable().Read(context, stream, OBJ_STRING_ID_NAME); + GetStringTable().Read(context, stream, OBJ_STRING_ID_DESCRIPTION); + GetStringTable().Read(context, stream, OBJ_STRING_ID_CAPACITY); // Read preset colours, by default there are 32 _presetColours.count = stream->ReadValue(); @@ -110,7 +110,7 @@ void RideObject::ReadLegacy(IReadObjectContext * context, IStream * stream) _peepLoadingPositionsCount[i] = numPeepLoadingPositions; } - GetImageTable()->Read(context, stream); + GetImageTable().Read(context, stream); // Validate properties if (_legacyType.excitement_multiplier > 75) @@ -131,11 +131,11 @@ void RideObject::ReadLegacy(IReadObjectContext * context, IStream * stream) void RideObject::Load() { - GetStringTable()->Sort(); + GetStringTable().Sort(); _legacyType.naming.name = language_allocate_object_string(GetName()); _legacyType.naming.description = language_allocate_object_string(GetDescription()); _legacyType.capacity = language_allocate_object_string(GetCapacity()); - _legacyType.images_offset = gfx_object_allocate_images(GetImageTable()->GetImages(), GetImageTable()->GetCount()); + _legacyType.images_offset = gfx_object_allocate_images(GetImageTable().GetImages(), GetImageTable().GetCount()); _legacyType.vehicle_preset_list = &_presetColours; sint32 cur_vehicle_images_offset = _legacyType.images_offset + MAX_RIDE_TYPES_PER_RIDE_ENTRY; @@ -300,7 +300,7 @@ void RideObject::Unload() language_free_object_string(_legacyType.naming.name); language_free_object_string(_legacyType.naming.description); language_free_object_string(_legacyType.capacity); - gfx_object_free_images(_legacyType.images_offset, GetImageTable()->GetCount()); + gfx_object_free_images(_legacyType.images_offset, GetImageTable().GetCount()); _legacyType.naming.name = 0; _legacyType.naming.description = 0; @@ -730,6 +730,6 @@ void RideObject::ReadJson(IReadObjectContext * context, const json_t * root) vehicle0->sprite_flags |= VEHICLE_SPRITE_FLAG_FLAT; vehicle0->base_image_id = 0; - ObjectJsonHelpers::LoadStrings(root, *GetStringTable()); - ObjectJsonHelpers::LoadImages(root, *GetImageTable()); + ObjectJsonHelpers::LoadStrings(root, GetStringTable()); + ObjectJsonHelpers::LoadImages(root, GetImageTable()); } diff --git a/src/openrct2/object/SceneryGroupObject.cpp b/src/openrct2/object/SceneryGroupObject.cpp index 8db99f469f..e137461e21 100644 --- a/src/openrct2/object/SceneryGroupObject.cpp +++ b/src/openrct2/object/SceneryGroupObject.cpp @@ -40,16 +40,16 @@ void SceneryGroupObject::ReadLegacy(IReadObjectContext * context, IStream * stre void SceneryGroupObject::Load() { - GetStringTable()->Sort(); + GetStringTable().Sort(); _legacyType.name = language_allocate_object_string(GetName()); - _legacyType.image = gfx_object_allocate_images(GetImageTable()->GetImages(), GetImageTable()->GetCount()); + _legacyType.image = gfx_object_allocate_images(GetImageTable().GetImages(), GetImageTable().GetCount()); _legacyType.entry_count = 0; } void SceneryGroupObject::Unload() { language_free_object_string(_legacyType.name); - gfx_object_free_images(_legacyType.image, GetImageTable()->GetCount()); + gfx_object_free_images(_legacyType.image, GetImageTable().GetCount()); _legacyType.name = 0; _legacyType.image = 0; diff --git a/src/openrct2/object/SmallSceneryObject.cpp b/src/openrct2/object/SmallSceneryObject.cpp index 357bf3d243..24a2e43bec 100644 --- a/src/openrct2/object/SmallSceneryObject.cpp +++ b/src/openrct2/object/SmallSceneryObject.cpp @@ -39,7 +39,7 @@ void SmallSceneryObject::ReadLegacy(IReadObjectContext * context, IStream * stre _legacyType.small_scenery.num_frames = stream->ReadValue(); _legacyType.small_scenery.scenery_tab_id = 0xFF; - GetStringTable()->Read(context, stream, OBJ_STRING_ID_NAME); + GetStringTable().Read(context, stream, OBJ_STRING_ID_NAME); rct_object_entry sgEntry = stream->ReadValue(); SetPrimarySceneryGroup(&sgEntry); @@ -49,7 +49,7 @@ void SmallSceneryObject::ReadLegacy(IReadObjectContext * context, IStream * stre _frameOffsets = ReadFrameOffsets(stream); } - GetImageTable()->Read(context, stream); + GetImageTable().Read(context, stream); // Validate properties if (_legacyType.small_scenery.price <= 0) @@ -69,9 +69,9 @@ void SmallSceneryObject::ReadLegacy(IReadObjectContext * context, IStream * stre void SmallSceneryObject::Load() { - GetStringTable()->Sort(); + GetStringTable().Sort(); _legacyType.name = language_allocate_object_string(GetName()); - _legacyType.image = gfx_object_allocate_images(GetImageTable()->GetImages(), GetImageTable()->GetCount()); + _legacyType.image = gfx_object_allocate_images(GetImageTable().GetImages(), GetImageTable().GetCount()); _legacyType.small_scenery.scenery_tab_id = 0xFF; @@ -86,7 +86,7 @@ void SmallSceneryObject::Load() void SmallSceneryObject::Unload() { language_free_object_string(_legacyType.name); - gfx_object_free_images(_legacyType.image, GetImageTable()->GetCount()); + gfx_object_free_images(_legacyType.image, GetImageTable().GetCount()); _legacyType.name = 0; _legacyType.image = 0; diff --git a/src/openrct2/object/StexObject.cpp b/src/openrct2/object/StexObject.cpp index 88137fb98f..810834e099 100644 --- a/src/openrct2/object/StexObject.cpp +++ b/src/openrct2/object/StexObject.cpp @@ -25,14 +25,14 @@ void StexObject::ReadLegacy(IReadObjectContext * context, IStream * stream) _legacyType.var_06 = stream->ReadValue(); stream->Seek(1, STREAM_SEEK_CURRENT); - GetStringTable()->Read(context, stream, OBJ_STRING_ID_SCENARIO_NAME); - GetStringTable()->Read(context, stream, OBJ_STRING_ID_PARK_NAME); - GetStringTable()->Read(context, stream, OBJ_STRING_ID_SCENARIO_DETAILS); + GetStringTable().Read(context, stream, OBJ_STRING_ID_SCENARIO_NAME); + GetStringTable().Read(context, stream, OBJ_STRING_ID_PARK_NAME); + GetStringTable().Read(context, stream, OBJ_STRING_ID_SCENARIO_DETAILS); } void StexObject::Load() { - GetStringTable()->Sort(); + GetStringTable().Sort(); _legacyType.scenario_name = language_allocate_object_string(GetScenarioName()); _legacyType.park_name = language_allocate_object_string(GetParkName()); _legacyType.details = language_allocate_object_string(GetScenarioDetails()); @@ -64,15 +64,15 @@ std::string StexObject::GetName() const std::string StexObject::GetScenarioName() const { - return GetStringTable()->GetString(OBJ_STRING_ID_SCENARIO_NAME); + return GetStringTable().GetString(OBJ_STRING_ID_SCENARIO_NAME); } std::string StexObject::GetScenarioDetails() const { - return GetStringTable()->GetString(OBJ_STRING_ID_SCENARIO_DETAILS); + return GetStringTable().GetString(OBJ_STRING_ID_SCENARIO_DETAILS); } std::string StexObject::GetParkName() const { - return GetStringTable()->GetString(OBJ_STRING_ID_PARK_NAME); + return GetStringTable().GetString(OBJ_STRING_ID_PARK_NAME); } diff --git a/src/openrct2/object/StringTable.h b/src/openrct2/object/StringTable.h index c370971bbe..34fa8de21a 100644 --- a/src/openrct2/object/StringTable.h +++ b/src/openrct2/object/StringTable.h @@ -19,14 +19,27 @@ #include #include #include "../common.h" +#include "../localisation/Language.h" interface IReadObjectContext; interface IStream; +enum OBJ_STRING_ID : uint8 +{ + OBJ_STRING_ID_UNKNOWN = 255, + OBJ_STRING_ID_NAME = 0, + OBJ_STRING_ID_DESCRIPTION, + OBJ_STRING_ID_SCENARIO_NAME = 0, + OBJ_STRING_ID_PARK_NAME = 1, + OBJ_STRING_ID_SCENARIO_DETAILS = 2, + OBJ_STRING_ID_CAPACITY = 2, + OBJ_STRING_ID_VEHICLE_NAME = 3, +}; + struct StringTableEntry { - uint8 Id; - uint8 LanguageId; + uint8 Id = OBJ_STRING_ID_UNKNOWN; + uint8 LanguageId = LANGUAGE_UNDEFINED; std::string Text; }; @@ -36,6 +49,10 @@ private: std::vector _strings; public: + StringTable() = default; + StringTable(const StringTable &) = delete; + StringTable & operator=(const StringTable &) = delete; + void Read(IReadObjectContext * context, IStream * stream, uint8 id); void Sort(); std::string GetString(uint8 id) const; diff --git a/src/openrct2/object/WallObject.cpp b/src/openrct2/object/WallObject.cpp index d6100b2d21..4f1ad39de8 100644 --- a/src/openrct2/object/WallObject.cpp +++ b/src/openrct2/object/WallObject.cpp @@ -31,12 +31,12 @@ void WallObject::ReadLegacy(IReadObjectContext * context, IStream * stream) _legacyType.wall.scenery_tab_id = stream->ReadValue(); _legacyType.wall.scrolling_mode = stream->ReadValue(); - GetStringTable()->Read(context, stream, OBJ_STRING_ID_NAME); + GetStringTable().Read(context, stream, OBJ_STRING_ID_NAME); rct_object_entry sgEntry = stream->ReadValue(); SetPrimarySceneryGroup(&sgEntry); - GetImageTable()->Read(context, stream); + GetImageTable().Read(context, stream); // Validate properties if (_legacyType.wall.price <= 0) @@ -47,15 +47,15 @@ void WallObject::ReadLegacy(IReadObjectContext * context, IStream * stream) void WallObject::Load() { - GetStringTable()->Sort(); + GetStringTable().Sort(); _legacyType.name = language_allocate_object_string(GetName()); - _legacyType.image = gfx_object_allocate_images(GetImageTable()->GetImages(), GetImageTable()->GetCount()); + _legacyType.image = gfx_object_allocate_images(GetImageTable().GetImages(), GetImageTable().GetCount()); } void WallObject::Unload() { language_free_object_string(_legacyType.name); - gfx_object_free_images(_legacyType.image, GetImageTable()->GetCount()); + gfx_object_free_images(_legacyType.image, GetImageTable().GetCount()); _legacyType.name = 0; _legacyType.image = 0; diff --git a/src/openrct2/object/WaterObject.cpp b/src/openrct2/object/WaterObject.cpp index e90e107c47..70fa3ee34e 100644 --- a/src/openrct2/object/WaterObject.cpp +++ b/src/openrct2/object/WaterObject.cpp @@ -25,15 +25,15 @@ void WaterObject::ReadLegacy(IReadObjectContext * context, IStream * stream) stream->Seek(14, STREAM_SEEK_CURRENT); _legacyType.flags = stream->ReadValue(); - GetStringTable()->Read(context, stream, OBJ_STRING_ID_NAME); - GetImageTable()->Read(context, stream); + GetStringTable().Read(context, stream, OBJ_STRING_ID_NAME); + GetImageTable().Read(context, stream); } void WaterObject::Load() { - GetStringTable()->Sort(); + GetStringTable().Sort(); _legacyType.string_idx = language_allocate_object_string(GetName()); - _legacyType.image_id = gfx_object_allocate_images(GetImageTable()->GetImages(), GetImageTable()->GetCount()); + _legacyType.image_id = gfx_object_allocate_images(GetImageTable().GetImages(), GetImageTable().GetCount()); _legacyType.palette_index_1 = _legacyType.image_id + 1; _legacyType.palette_index_2 = _legacyType.image_id + 4; @@ -42,7 +42,7 @@ void WaterObject::Load() void WaterObject::Unload() { - gfx_object_free_images(_legacyType.image_id, GetImageTable()->GetCount()); + gfx_object_free_images(_legacyType.image_id, GetImageTable().GetCount()); language_free_object_string(_legacyType.string_idx); _legacyType.string_idx = 0; From 12d2523752fd91ec8d1c38abe872d0d01cc52349 Mon Sep 17 00:00:00 2001 From: Ted John Date: Mon, 11 Dec 2017 22:01:56 +0000 Subject: [PATCH 24/93] Add JSON loading for footpath banners --- src/openrct2/object/BannerObject.cpp | 19 +++++++++++++++++-- src/openrct2/object/BannerObject.h | 1 + src/openrct2/object/FootpathItemObject.cpp | 8 +------- src/openrct2/object/ObjectFactory.cpp | 1 + src/openrct2/object/SceneryObject.h | 10 ++++++++++ 5 files changed, 30 insertions(+), 9 deletions(-) diff --git a/src/openrct2/object/BannerObject.cpp b/src/openrct2/object/BannerObject.cpp index a70cb659f3..625b8bdb18 100644 --- a/src/openrct2/object/BannerObject.cpp +++ b/src/openrct2/object/BannerObject.cpp @@ -15,11 +15,11 @@ #pragma endregion #include "../core/IStream.hpp" -#include "BannerObject.h" - #include "../drawing/Drawing.h" #include "../localisation/Language.h" #include "../object/Object.h" +#include "BannerObject.h" +#include "ObjectJsonHelpers.h" #include "ObjectList.h" void BannerObject::ReadLegacy(IReadObjectContext * context, IStream * stream) @@ -84,3 +84,18 @@ void BannerObject::DrawPreview(rct_drawpixelinfo * dpi, sint32 width, sint32 hei gfx_draw_sprite(dpi, imageId + 0, x - 12, y + 8, 0); gfx_draw_sprite(dpi, imageId + 1, x - 12, y + 8, 0); } + +void BannerObject::ReadJson(IReadObjectContext * context, const json_t * root) +{ + auto properties = json_object_get(root, "properties"); + + _legacyType.banner.scrolling_mode = json_integer_value(json_object_get(properties, "scrollingMode")); + _legacyType.banner.price = json_integer_value(json_object_get(properties, "price")); + _legacyType.banner.flags = ObjectJsonHelpers::GetFlags(properties, { + { "hasPrimaryColour", BANNER_ENTRY_FLAG_HAS_PRIMARY_COLOUR }}); + + SetPrimarySceneryGroup(ObjectJsonHelpers::GetString(json_object_get(properties, "sceneryGroup"))); + + ObjectJsonHelpers::LoadStrings(root, GetStringTable()); + ObjectJsonHelpers::LoadImages(root, GetImageTable()); +} diff --git a/src/openrct2/object/BannerObject.h b/src/openrct2/object/BannerObject.h index 1dedd329d2..0f1148e753 100644 --- a/src/openrct2/object/BannerObject.h +++ b/src/openrct2/object/BannerObject.h @@ -31,6 +31,7 @@ public: void * GetLegacyData() override { return &_legacyType; } void ReadLegacy(IReadObjectContext * context, IStream * stream) override; + void ReadJson(IReadObjectContext * context, const json_t * root) override; void Load() override; void Unload() override; diff --git a/src/openrct2/object/FootpathItemObject.cpp b/src/openrct2/object/FootpathItemObject.cpp index e864d85cbb..fd2b2e4f99 100644 --- a/src/openrct2/object/FootpathItemObject.cpp +++ b/src/openrct2/object/FootpathItemObject.cpp @@ -142,13 +142,7 @@ void FootpathItemObject::ReadJson(IReadObjectContext * context, const json_t * r _legacyType.path_bit.tool_id = ParseCursor(ObjectJsonHelpers::GetString(json_object_get(properties, "cursor"))); _legacyType.path_bit.price = json_integer_value(json_object_get(properties, "price")); - auto scg = ObjectJsonHelpers::GetString(json_object_get(properties, "sceneryGroup")); - if (!scg.empty()) - { - rct_object_entry sgEntry = { 0 }; - strncpy(sgEntry.name, scg.c_str(), 8); - SetPrimarySceneryGroup(&sgEntry); - } + SetPrimarySceneryGroup(ObjectJsonHelpers::GetString(json_object_get(properties, "sceneryGroup"))); // Flags _legacyType.path_bit.flags = ObjectJsonHelpers::GetFlags(properties, { diff --git a/src/openrct2/object/ObjectFactory.cpp b/src/openrct2/object/ObjectFactory.cpp index e7494502c6..1064fb76a1 100644 --- a/src/openrct2/object/ObjectFactory.cpp +++ b/src/openrct2/object/ObjectFactory.cpp @@ -209,6 +209,7 @@ namespace ObjectFactory { if (s == "ride") return OBJECT_TYPE_RIDE; if (s == "footpath") return OBJECT_TYPE_PATHS; + if (s == "footpath_banner") return OBJECT_TYPE_BANNERS; if (s == "footpath_item") return OBJECT_TYPE_PATH_BITS; if (s == "park_entrance") return OBJECT_TYPE_PARK_ENTRANCE; return 0xFF; diff --git a/src/openrct2/object/SceneryObject.h b/src/openrct2/object/SceneryObject.h index 18a1386ad7..4d3cb9d693 100644 --- a/src/openrct2/object/SceneryObject.h +++ b/src/openrct2/object/SceneryObject.h @@ -16,6 +16,7 @@ #pragma once +#include #include "Object.h" class SceneryObject : public Object @@ -31,4 +32,13 @@ public: protected: void SetPrimarySceneryGroup(const rct_object_entry * entry) { _primarySceneryGroupEntry = *entry; } + void SetPrimarySceneryGroup(const std::string &s) + { + if (!s.empty()) + { + rct_object_entry sgEntry = { 0 }; + std::strncpy(sgEntry.name, s.c_str(), 8); + SetPrimarySceneryGroup(&sgEntry); + } + } }; From 40f775c39a3de454b2d0e83b195c10104bfb0fa4 Mon Sep 17 00:00:00 2001 From: Ted John Date: Thu, 14 Dec 2017 13:28:08 +0000 Subject: [PATCH 25/93] Add JSON loading for water --- src/openrct2/object/WaterObject.cpp | 84 +++++++++++++++++++++++++++++ src/openrct2/object/WaterObject.h | 9 +++- 2 files changed, 91 insertions(+), 2 deletions(-) diff --git a/src/openrct2/object/WaterObject.cpp b/src/openrct2/object/WaterObject.cpp index 70fa3ee34e..c18c9ccfd3 100644 --- a/src/openrct2/object/WaterObject.cpp +++ b/src/openrct2/object/WaterObject.cpp @@ -14,10 +14,14 @@ *****************************************************************************/ #pragma endregion +#pragma warning(disable : 4706) // assignment within conditional expression + +#include #include "../core/IStream.hpp" #include "../localisation/Language.h" #include "../localisation/StringIds.h" #include "../OpenRCT2.h" +#include "ObjectJsonHelpers.h" #include "WaterObject.h" void WaterObject::ReadLegacy(IReadObjectContext * context, IStream * stream) @@ -55,3 +59,83 @@ void WaterObject::DrawPreview(rct_drawpixelinfo * dpi, sint32 width, sint32 heig sint32 y = height / 2; gfx_draw_string_centred(dpi, STR_WINDOW_NO_IMAGE, x, y, COLOUR_BLACK, nullptr); } + +void WaterObject::ReadJson(IReadObjectContext * context, const json_t * root) +{ + auto properties = json_object_get(root, "properties"); + _legacyType.flags = ObjectJsonHelpers::GetFlags(properties, { + { "allowDucks", WATER_FLAGS_ALLOW_DUCKS }}); + + ObjectJsonHelpers::LoadStrings(root, GetStringTable()); + + // Images which are actually palette data + static const char * paletteNames[] = + { + "general", + "waves-0", + "waves-1", + "waves-2", + "sparkles-0", + "sparkles-1", + "sparkles-2" + }; + for (auto paletteName : paletteNames) + { + auto jPalettes = json_object_get(properties, "palettes"); + if (jPalettes != nullptr) + { + auto jPalette = json_object_get(jPalettes, paletteName); + if (jPalette != nullptr) + { + ReadJsonPalette(jPalette); + } + } + } +} + +void WaterObject::ReadJsonPalette(const json_t * jPalette) +{ + auto paletteStartIndex = json_integer_value(json_object_get(jPalette, "index")); + auto jColours = json_object_get(jPalette, "colours"); + auto numColours = json_array_size(jColours); + + auto data = std::make_unique(numColours); + size_t dataIndex = 0; + + size_t index; + const json_t * jColour; + json_array_foreach(jColours, index, jColour) + { + auto szColour = json_string_value(jColour); + if (szColour != nullptr) + { + auto colour = ParseColour(szColour); + data[dataIndex + 0] = colour; + data[dataIndex + 1] = (colour >> 8) & 0xFF; + data[dataIndex + 2] = (colour >> 16) & 0xFF; + } + dataIndex += 3; + } + + rct_g1_element g1 = { 0 }; + g1.offset = data.get(); + g1.x_offset = (sint16)paletteStartIndex; + + auto &imageTable = GetImageTable(); + imageTable.AddImage(&g1); +} + +uint32 WaterObject::ParseColour(const std::string &s) const +{ + uint8 r = 0; + uint8 g = 0; + uint8 b = 0; + if (s[0] == '#' && s.size() == 7) + { + // Expect #RRGGBB + r = std::stoul(s.substr(1, 2), nullptr, 16) & 0xFF; + g = std::stoul(s.substr(3, 2), nullptr, 16) & 0xFF; + b = std::stoul(s.substr(5, 2), nullptr, 16) & 0xFF; + } + return (b << 16) | (g << 8) | r; +} diff --git a/src/openrct2/object/WaterObject.h b/src/openrct2/object/WaterObject.h index e1c7a6ec1e..7b30929d26 100644 --- a/src/openrct2/object/WaterObject.h +++ b/src/openrct2/object/WaterObject.h @@ -16,9 +16,9 @@ #pragma once -#include "Object.h" - +#include #include "../world/Water.h" +#include "Object.h" class WaterObject final : public Object { @@ -30,9 +30,14 @@ public: void * GetLegacyData() override { return &_legacyType; } + void ReadJson(IReadObjectContext * context, const json_t * root) override; void ReadLegacy(IReadObjectContext * context, IStream * stream) override; void Load() override; void Unload() override; void DrawPreview(rct_drawpixelinfo * dpi, sint32 width, sint32 height) const override; + +private: + void ReadJsonPalette(const json_t * jPalette); + uint32 ParseColour(const std::string &s) const; }; From 3ead0f4289cce2329b46f993eeefd609e9805dba Mon Sep 17 00:00:00 2001 From: Ted John Date: Thu, 14 Dec 2017 17:35:34 +0000 Subject: [PATCH 26/93] Finish loading water JSON objects --- src/openrct2/drawing/Drawing.h | 1 + src/openrct2/drawing/Sprite.cpp | 15 ++------------- src/openrct2/object/ObjectFactory.cpp | 1 + src/openrct2/object/WaterObject.cpp | 8 +++++--- 4 files changed, 9 insertions(+), 16 deletions(-) diff --git a/src/openrct2/drawing/Drawing.h b/src/openrct2/drawing/Drawing.h index 2346351e8d..54d7d5d647 100644 --- a/src/openrct2/drawing/Drawing.h +++ b/src/openrct2/drawing/Drawing.h @@ -56,6 +56,7 @@ enum { G1_FLAG_BMP = (1 << 0), // Image data is encoded as raw pixels (no transparency) G1_FLAG_1 = (1 << 1), G1_FLAG_RLE_COMPRESSION = (1 << 2), // Image data is encoded using RCT2's form of run length encoding + G1_FLAG_PALETTE = (1 << 3), // Image data is a sequence of palette entries R8G8B8 G1_FLAG_HAS_ZOOM_SPRITE = (1 << 4), // Use a different sprite for higher zoom levels G1_FLAG_NO_ZOOM_DRAW = (1 << 5), // Does not get drawn at higher zoom levels (only zoom 0) }; diff --git a/src/openrct2/drawing/Sprite.cpp b/src/openrct2/drawing/Sprite.cpp index 9e7442ebbc..0f34364295 100644 --- a/src/openrct2/drawing/Sprite.cpp +++ b/src/openrct2/drawing/Sprite.cpp @@ -863,20 +863,9 @@ rct_size16 FASTCALL gfx_get_sprite_size(uint32 image_id) size_t g1_calculate_data_size(const rct_g1_element * g1) { - if (g1->flags & G1_FLAG_RLE_COMPRESSION) + if (g1->flags & G1_FLAG_PALETTE) { - uint16 * offsets = (uint16 *)g1->offset; - uint8 * ptr = g1->offset + offsets[g1->height - 1]; - bool endOfLine = false; - do - { - uint8 chunk0 = *ptr++; - ptr++; // offset - uint8 chunkSize = chunk0 & 0x7F; - ptr += chunkSize; - endOfLine = (chunk0 & 0x80) != 0; - } while (!endOfLine); - return ptr - g1->offset; + return g1->width * 3; } else if (g1->flags & G1_FLAG_RLE_COMPRESSION) { diff --git a/src/openrct2/object/ObjectFactory.cpp b/src/openrct2/object/ObjectFactory.cpp index 1064fb76a1..d16cc7af3e 100644 --- a/src/openrct2/object/ObjectFactory.cpp +++ b/src/openrct2/object/ObjectFactory.cpp @@ -212,6 +212,7 @@ namespace ObjectFactory if (s == "footpath_banner") return OBJECT_TYPE_BANNERS; if (s == "footpath_item") return OBJECT_TYPE_PATH_BITS; if (s == "park_entrance") return OBJECT_TYPE_PARK_ENTRANCE; + if (s == "water") return OBJECT_TYPE_WATER; return 0xFF; } diff --git a/src/openrct2/object/WaterObject.cpp b/src/openrct2/object/WaterObject.cpp index c18c9ccfd3..2edcc3c338 100644 --- a/src/openrct2/object/WaterObject.cpp +++ b/src/openrct2/object/WaterObject.cpp @@ -99,7 +99,7 @@ void WaterObject::ReadJsonPalette(const json_t * jPalette) auto jColours = json_object_get(jPalette, "colours"); auto numColours = json_array_size(jColours); - auto data = std::make_unique(numColours); + auto data = std::make_unique(numColours * 3); size_t dataIndex = 0; size_t index; @@ -110,16 +110,18 @@ void WaterObject::ReadJsonPalette(const json_t * jPalette) if (szColour != nullptr) { auto colour = ParseColour(szColour); - data[dataIndex + 0] = colour; + data[dataIndex + 0] = (colour >> 16) & 0xFF; data[dataIndex + 1] = (colour >> 8) & 0xFF; - data[dataIndex + 2] = (colour >> 16) & 0xFF; + data[dataIndex + 2] = colour & 0xFF; } dataIndex += 3; } rct_g1_element g1 = { 0 }; g1.offset = data.get(); + g1.width = (sint16)numColours; g1.x_offset = (sint16)paletteStartIndex; + g1.flags = G1_FLAG_PALETTE; auto &imageTable = GetImageTable(); imageTable.AddImage(&g1); From ede51ded86363944dd853cdc1fae3319cf706729 Mon Sep 17 00:00:00 2001 From: Ted John Date: Thu, 14 Dec 2017 18:43:59 +0000 Subject: [PATCH 27/93] Add JSON loading for scenery groups --- src/openrct2/object/ObjectFactory.cpp | 1 + src/openrct2/object/ObjectJsonHelpers.cpp | 9 ++ src/openrct2/object/ObjectJsonHelpers.h | 2 + src/openrct2/object/SceneryGroupObject.cpp | 102 ++++++++++++++++++--- src/openrct2/object/SceneryGroupObject.h | 4 + src/openrct2/object/SceneryObject.cpp | 27 ++++++ src/openrct2/object/SceneryObject.h | 10 +- 7 files changed, 135 insertions(+), 20 deletions(-) create mode 100644 src/openrct2/object/SceneryObject.cpp diff --git a/src/openrct2/object/ObjectFactory.cpp b/src/openrct2/object/ObjectFactory.cpp index d16cc7af3e..ca5b6b8b89 100644 --- a/src/openrct2/object/ObjectFactory.cpp +++ b/src/openrct2/object/ObjectFactory.cpp @@ -211,6 +211,7 @@ namespace ObjectFactory if (s == "footpath") return OBJECT_TYPE_PATHS; if (s == "footpath_banner") return OBJECT_TYPE_BANNERS; if (s == "footpath_item") return OBJECT_TYPE_PATH_BITS; + if (s == "scenery_group") return OBJECT_TYPE_SCENERY_GROUP; if (s == "park_entrance") return OBJECT_TYPE_PARK_ENTRANCE; if (s == "water") return OBJECT_TYPE_WATER; return 0xFF; diff --git a/src/openrct2/object/ObjectJsonHelpers.cpp b/src/openrct2/object/ObjectJsonHelpers.cpp index a47bf77b4d..cb7286f3a6 100644 --- a/src/openrct2/object/ObjectJsonHelpers.cpp +++ b/src/openrct2/object/ObjectJsonHelpers.cpp @@ -66,6 +66,15 @@ namespace ObjectJsonHelpers return result; } + rct_object_entry ParseObjectEntry(const std::string & s) + { + rct_object_entry entry = { 0 }; + std::fill_n(entry.name, sizeof(entry.name), ' '); + auto copyLen = std::min(8, s.size()); + std::copy_n(s.c_str(), copyLen, entry.name); + return entry; + } + static std::vector ParseRange(std::string s) { // Currently only supports [###] or [###..###] diff --git a/src/openrct2/object/ObjectJsonHelpers.h b/src/openrct2/object/ObjectJsonHelpers.h index c2edea2741..7cc3c11cb7 100644 --- a/src/openrct2/object/ObjectJsonHelpers.h +++ b/src/openrct2/object/ObjectJsonHelpers.h @@ -23,6 +23,7 @@ #include "../common.h" #include "../core/Json.hpp" #include "../drawing/drawing.h" +#include "../object.h" #include "ImageTable.h" #include "StringTable.h" @@ -31,6 +32,7 @@ namespace ObjectJsonHelpers bool GetBoolean(const json_t * obj, const std::string &name, bool defaultValue = false); std::string GetString(const json_t * value); std::vector GetJsonStringArray(const json_t * arr); + rct_object_entry ParseObjectEntry(const std::string & s); void LoadStrings(const json_t * root, StringTable &stringTable); void LoadImages(const json_t * root, ImageTable &imageTable); diff --git a/src/openrct2/object/SceneryGroupObject.cpp b/src/openrct2/object/SceneryGroupObject.cpp index e137461e21..e43827704f 100644 --- a/src/openrct2/object/SceneryGroupObject.cpp +++ b/src/openrct2/object/SceneryGroupObject.cpp @@ -14,15 +14,20 @@ *****************************************************************************/ #pragma endregion +#pragma warning(disable : 4706) // assignment within conditional expression + +#include #include "../core/IStream.hpp" #include "../core/Memory.hpp" +#include "../core/String.hpp" +#include "../drawing/Drawing.h" +#include "../localisation/Language.h" +#include "../peep/Staff.h" +#include "ObjectJsonHelpers.h" #include "ObjectManager.h" #include "ObjectRepository.h" #include "SceneryGroupObject.h" -#include "../drawing/Drawing.h" -#include "../localisation/Language.h" - void SceneryGroupObject::ReadLegacy(IReadObjectContext * context, IStream * stream) { stream->Seek(6, STREAM_SEEK_CURRENT); @@ -79,17 +84,20 @@ void SceneryGroupObject::UpdateEntryIndexes() uint16 sceneryEntry = objectManager->GetLoadedObjectEntryIndex(ori->LoadedObject); Guard::Assert(sceneryEntry != UINT8_MAX, GUARD_LINE); - uint8 objectType = objectEntry.flags & 0x0F; + auto objectType = ori->ObjectEntry.flags & 0x0F; switch (objectType) { case OBJECT_TYPE_SMALL_SCENERY: break; - case OBJECT_TYPE_LARGE_SCENERY: sceneryEntry |= 0x300; break; - case OBJECT_TYPE_WALLS: sceneryEntry |= 0x200; break; case OBJECT_TYPE_PATH_BITS: sceneryEntry |= 0x100; break; - default: sceneryEntry |= 0x400; break; + case OBJECT_TYPE_WALLS: sceneryEntry |= 0x200; break; + case OBJECT_TYPE_LARGE_SCENERY: sceneryEntry |= 0x300; break; + case OBJECT_TYPE_BANNERS: sceneryEntry |= 0x400; break; + default: sceneryEntry = 0xFFFF; break; + } + if (sceneryEntry != 0xFFFF) + { + _legacyType.scenery_entries[_legacyType.entry_count] = sceneryEntry; + _legacyType.entry_count++; } - - _legacyType.scenery_entries[_legacyType.entry_count] = sceneryEntry; - _legacyType.entry_count++; } } @@ -111,8 +119,80 @@ std::vector SceneryGroupObject::ReadItems(IStream * stream) while (stream->ReadValue() != 0xFF) { stream->Seek(-1, STREAM_SEEK_CURRENT); - rct_object_entry entry = stream->ReadValue(); + auto entry = stream->ReadValue(); items.push_back(entry); } return items; } + +void SceneryGroupObject::ReadJson(IReadObjectContext * context, const json_t * root) +{ + auto properties = json_object_get(root, "properties"); + _legacyType.priority = json_integer_value(json_object_get(properties, "priority")); + + // Entertainer cosumes + auto jCostumes = json_object_get(properties, "entertainerCostumes"); + if (jCostumes != nullptr) + { + _legacyType.entertainer_costumes = ReadJsonEntertainerCostumes(jCostumes); + } + + auto jEntries = json_object_get(properties, "entries"); + if (jEntries != nullptr) + { + _items = ReadJsonEntries(jEntries); + } + + ObjectJsonHelpers::LoadStrings(root, GetStringTable()); + ObjectJsonHelpers::LoadImages(root, GetImageTable()); +} + +uint32 SceneryGroupObject::ReadJsonEntertainerCostumes(const json_t * jCostumes) +{ + uint32 costumes = 0; + size_t index; + json_t * jCostume; + json_array_foreach(jCostumes, index, jCostume) + { + auto costume = ObjectJsonHelpers::GetString(jCostume); + auto entertainer = ParseEntertainerCostume(costume); + + // For some reason the flags are +4 from the actual costume IDs + // See staff_get_available_entertainer_costumes + costumes |= 1 << (entertainer + 4); + } + return costumes; +} + +uint32 SceneryGroupObject::ParseEntertainerCostume(const std::string &s) +{ + if (s == "panda") return ENTERTAINER_COSTUME_PANDA; + if (s == "tiger") return ENTERTAINER_COSTUME_TIGER; + if (s == "elephant") return ENTERTAINER_COSTUME_ELEPHANT; + if (s == "roman") return ENTERTAINER_COSTUME_ROMAN; + if (s == "gorilla") return ENTERTAINER_COSTUME_GORILLA; + if (s == "snowman") return ENTERTAINER_COSTUME_SNOWMAN; + if (s == "knight") return ENTERTAINER_COSTUME_KNIGHT; + if (s == "astronaut") return ENTERTAINER_COSTUME_ASTRONAUT; + if (s == "bandit") return ENTERTAINER_COSTUME_BANDIT; + if (s == "sheriff") return ENTERTAINER_COSTUME_SHERIFF; + if (s == "pirate") return ENTERTAINER_COSTUME_PIRATE; + return ENTERTAINER_COSTUME_PANDA; +} + +std::vector SceneryGroupObject::ReadJsonEntries(const json_t * jEntries) +{ + std::vector entries; + size_t index; + json_t * jEntry; + json_array_foreach(jEntries, index, jEntry) + { + auto entryId = json_string_value(jEntry); + if (entryId != nullptr) + { + auto entry = ObjectJsonHelpers::ParseObjectEntry(entryId); + entries.push_back(entry); + } + } + return entries; +} diff --git a/src/openrct2/object/SceneryGroupObject.h b/src/openrct2/object/SceneryGroupObject.h index a4e6b9c5de..6c6cb47f75 100644 --- a/src/openrct2/object/SceneryGroupObject.h +++ b/src/openrct2/object/SceneryGroupObject.h @@ -32,6 +32,7 @@ public: explicit SceneryGroupObject(const rct_object_entry &entry) : Object(entry) { } void * GetLegacyData() override { return &_legacyType; } + void ReadJson(IReadObjectContext * context, const json_t * root) override; void ReadLegacy(IReadObjectContext * context, IStream * stream) override; void Load() override; @@ -44,4 +45,7 @@ public: private: static std::vector ReadItems(IStream * stream); + static uint32 ReadJsonEntertainerCostumes(const json_t * jCostumes); + static uint32 ParseEntertainerCostume(const std::string &s); + static std::vector ReadJsonEntries(const json_t * jEntries); }; diff --git a/src/openrct2/object/SceneryObject.cpp b/src/openrct2/object/SceneryObject.cpp new file mode 100644 index 0000000000..140239a8a6 --- /dev/null +++ b/src/openrct2/object/SceneryObject.cpp @@ -0,0 +1,27 @@ +#pragma region Copyright (c) 2014-2017 OpenRCT2 Developers +/***************************************************************************** +* OpenRCT2, an open source clone of Roller Coaster Tycoon 2. +* +* OpenRCT2 is the work of many authors, a full list can be found in contributors.md +* For more information, visit https://github.com/OpenRCT2/OpenRCT2 +* +* OpenRCT2 is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* A full copy of the GNU General Public License can be found in licence.txt +*****************************************************************************/ +#pragma endregion + +#include "ObjectJsonHelpers.h" +#include "SceneryObject.h" + +void SceneryObject::SetPrimarySceneryGroup(const std::string &s) +{ + if (!s.empty()) + { + auto sgEntry = ObjectJsonHelpers::ParseObjectEntry(s); + SetPrimarySceneryGroup(&sgEntry); + } +} diff --git a/src/openrct2/object/SceneryObject.h b/src/openrct2/object/SceneryObject.h index 4d3cb9d693..98ce7256c8 100644 --- a/src/openrct2/object/SceneryObject.h +++ b/src/openrct2/object/SceneryObject.h @@ -32,13 +32,5 @@ public: protected: void SetPrimarySceneryGroup(const rct_object_entry * entry) { _primarySceneryGroupEntry = *entry; } - void SetPrimarySceneryGroup(const std::string &s) - { - if (!s.empty()) - { - rct_object_entry sgEntry = { 0 }; - std::strncpy(sgEntry.name, s.c_str(), 8); - SetPrimarySceneryGroup(&sgEntry); - } - } + void SetPrimarySceneryGroup(const std::string &s); }; From f6a6169ca26a0d256690ffa3737544add94d74df Mon Sep 17 00:00:00 2001 From: Ted John Date: Sun, 17 Dec 2017 00:50:32 +0000 Subject: [PATCH 28/93] Don't report object conflicts --- src/openrct2/object/ObjectRepository.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/openrct2/object/ObjectRepository.cpp b/src/openrct2/object/ObjectRepository.cpp index 7b4387d672..b0887ac012 100644 --- a/src/openrct2/object/ObjectRepository.cpp +++ b/src/openrct2/object/ObjectRepository.cpp @@ -433,8 +433,9 @@ private: } else { - Console::Error::WriteLine("Object conflict: '%s'", conflict->Path); - Console::Error::WriteLine(" : '%s'", item.Path); + // Commented out temporarily to stop flooding terminal for json-objects branch + // Console::Error::WriteLine("Object conflict: '%s'", conflict->Path); + // Console::Error::WriteLine(" : '%s'", item.Path); return false; } } From 1d12fc796318f2de6dc322c4f6e15c5af1903cf4 Mon Sep 17 00:00:00 2001 From: Ted John Date: Sun, 17 Dec 2017 00:50:50 +0000 Subject: [PATCH 29/93] Update launch.json --- .vscode/launch.json | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 25c3c7a2bf..d3df614e53 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -1,19 +1,22 @@ { "version": "0.2.0", "configurations": [ + { "name": "C++ Launch", "type": "cppdbg", "request": "launch", - "program": "${workspaceRoot}/bin/openrct2", + "program": "${workspaceFolder}/bin/openrct2", "args": [], "stopAtEntry": false, - "cwd": "${workspaceRoot}/bin", + "cwd": "${workspaceFolder}/bin", "environment": [], "externalConsole": true, "setupCommands": [ { - "text": "-enable-pretty-printing" + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true } ], "linux": { @@ -30,7 +33,7 @@ "name": "C++ Attach", "type": "cppdbg", "request": "attach", - "program": "${workspaceRoot}/bin/openrct2", + "program": "${workspaceFolder}/bin/openrct2", "processId": "${command:pickProcess}", "setupCommands": [ { From 971e2dcaa22bc0239f372f7f4a64c714e355767f Mon Sep 17 00:00:00 2001 From: Ted John Date: Sun, 17 Dec 2017 00:51:13 +0000 Subject: [PATCH 30/93] Add JSON loading for walls --- src/openrct2/object/FootpathItemObject.cpp | 43 +---------- src/openrct2/object/ObjectFactory.cpp | 1 + src/openrct2/object/ObjectJsonHelpers.cpp | 86 +++++++++++++++++++--- src/openrct2/object/ObjectJsonHelpers.h | 2 + src/openrct2/object/WallObject.cpp | 63 +++++++++++++++- src/openrct2/object/WallObject.h | 1 + 6 files changed, 144 insertions(+), 52 deletions(-) diff --git a/src/openrct2/object/FootpathItemObject.cpp b/src/openrct2/object/FootpathItemObject.cpp index fd2b2e4f99..78006e1186 100644 --- a/src/openrct2/object/FootpathItemObject.cpp +++ b/src/openrct2/object/FootpathItemObject.cpp @@ -96,50 +96,11 @@ static uint8 ParseDrawType(const std::string &s) return PATH_BIT_DRAW_TYPE_LIGHTS; } -static uint8 ParseCursor(const std::string &s) -{ - static const std::unordered_map LookupTable - { - { "CURSOR_BLANK", CURSOR_BLANK }, - { "CURSOR_UP_ARROW", CURSOR_UP_ARROW }, - { "CURSOR_UP_DOWN_ARROW", CURSOR_UP_DOWN_ARROW }, - { "CURSOR_HAND_POINT", CURSOR_HAND_POINT }, - { "CURSOR_ZZZ", CURSOR_ZZZ }, - { "CURSOR_DIAGONAL_ARROWS", CURSOR_DIAGONAL_ARROWS }, - { "CURSOR_PICKER", CURSOR_PICKER }, - { "CURSOR_TREE_DOWN", CURSOR_TREE_DOWN }, - { "CURSOR_FOUNTAIN_DOWN", CURSOR_FOUNTAIN_DOWN }, - { "CURSOR_STATUE_DOWN", CURSOR_STATUE_DOWN }, - { "CURSOR_BENCH_DOWN", CURSOR_BENCH_DOWN }, - { "CURSOR_CROSS_HAIR", CURSOR_CROSS_HAIR }, - { "CURSOR_BIN_DOWN", CURSOR_BIN_DOWN }, - { "CURSOR_LAMPPOST_DOWN", CURSOR_LAMPPOST_DOWN }, - { "CURSOR_FENCE_DOWN", CURSOR_FENCE_DOWN }, - { "CURSOR_FLOWER_DOWN", CURSOR_FLOWER_DOWN }, - { "CURSOR_PATH_DOWN", CURSOR_PATH_DOWN }, - { "CURSOR_DIG_DOWN", CURSOR_DIG_DOWN }, - { "CURSOR_WATER_DOWN", CURSOR_WATER_DOWN }, - { "CURSOR_HOUSE_DOWN", CURSOR_HOUSE_DOWN }, - { "CURSOR_VOLCANO_DOWN", CURSOR_VOLCANO_DOWN }, - { "CURSOR_WALK_DOWN", CURSOR_WALK_DOWN }, - { "CURSOR_PAINT_DOWN", CURSOR_PAINT_DOWN }, - { "CURSOR_ENTRANCE_DOWN", CURSOR_ENTRANCE_DOWN }, - { "CURSOR_HAND_OPEN", CURSOR_HAND_OPEN }, - { "CURSOR_HAND_CLOSED", CURSOR_HAND_CLOSED }, - {"CURSOR_ARROW", CURSOR_ARROW }, - }; - - auto result = LookupTable.find(s); - return (result != LookupTable.end()) ? - result->second : - CURSOR_ARROW; -} - void FootpathItemObject::ReadJson(IReadObjectContext * context, const json_t * root) { auto properties = json_object_get(root, "properties"); - _legacyType.path_bit.draw_type = ParseDrawType(ObjectJsonHelpers::GetString(json_object_get(properties, "renderAs"))); - _legacyType.path_bit.tool_id = ParseCursor(ObjectJsonHelpers::GetString(json_object_get(properties, "cursor"))); + _legacyType.path_bit.draw_type = ParseDrawType(ObjectJsonHelpers::GetString(properties, "renderAs")); + _legacyType.path_bit.tool_id = ObjectJsonHelpers::ParseCursor(ObjectJsonHelpers::GetString(properties, "cursor"), CURSOR_LAMPPOST_DOWN); _legacyType.path_bit.price = json_integer_value(json_object_get(properties, "price")); SetPrimarySceneryGroup(ObjectJsonHelpers::GetString(json_object_get(properties, "sceneryGroup"))); diff --git a/src/openrct2/object/ObjectFactory.cpp b/src/openrct2/object/ObjectFactory.cpp index ca5b6b8b89..48fd44d35b 100644 --- a/src/openrct2/object/ObjectFactory.cpp +++ b/src/openrct2/object/ObjectFactory.cpp @@ -211,6 +211,7 @@ namespace ObjectFactory if (s == "footpath") return OBJECT_TYPE_PATHS; if (s == "footpath_banner") return OBJECT_TYPE_BANNERS; if (s == "footpath_item") return OBJECT_TYPE_PATH_BITS; + if (s == "scenery_wall") return OBJECT_TYPE_WALLS; if (s == "scenery_group") return OBJECT_TYPE_SCENERY_GROUP; if (s == "park_entrance") return OBJECT_TYPE_PARK_ENTRANCE; if (s == "water") return OBJECT_TYPE_WATER; diff --git a/src/openrct2/object/ObjectJsonHelpers.cpp b/src/openrct2/object/ObjectJsonHelpers.cpp index cb7286f3a6..e8519e7885 100644 --- a/src/openrct2/object/ObjectJsonHelpers.cpp +++ b/src/openrct2/object/ObjectJsonHelpers.cpp @@ -16,11 +16,13 @@ #pragma warning(disable : 4706) // assignment within conditional expression +#include #include "../Context.h" #include "../core/Math.hpp" #include "../core/Memory.hpp" #include "../core/Path.hpp" #include "../core/String.hpp" +#include "../interface/Cursors.h" #include "../localisation/language.h" #include "../PlatformEnvironment.h" #include "../sprites.h" @@ -47,6 +49,14 @@ namespace ObjectJsonHelpers std::string(); } + std::string GetString(const json_t * obj, const std::string &name, const std::string &defaultValue) + { + auto value = json_object_get(obj, name.c_str()); + return json_is_string(value) ? + json_string_value(value) : + defaultValue; + } + std::vector GetJsonStringArray(const json_t * arr) { std::vector result; @@ -66,6 +76,45 @@ namespace ObjectJsonHelpers return result; } + uint8 ParseCursor(const std::string &s, uint8 defaultValue) + { + static const std::unordered_map LookupTable + { + { "CURSOR_BLANK", CURSOR_BLANK }, + { "CURSOR_UP_ARROW", CURSOR_UP_ARROW }, + { "CURSOR_UP_DOWN_ARROW", CURSOR_UP_DOWN_ARROW }, + { "CURSOR_HAND_POINT", CURSOR_HAND_POINT }, + { "CURSOR_ZZZ", CURSOR_ZZZ }, + { "CURSOR_DIAGONAL_ARROWS", CURSOR_DIAGONAL_ARROWS }, + { "CURSOR_PICKER", CURSOR_PICKER }, + { "CURSOR_TREE_DOWN", CURSOR_TREE_DOWN }, + { "CURSOR_FOUNTAIN_DOWN", CURSOR_FOUNTAIN_DOWN }, + { "CURSOR_STATUE_DOWN", CURSOR_STATUE_DOWN }, + { "CURSOR_BENCH_DOWN", CURSOR_BENCH_DOWN }, + { "CURSOR_CROSS_HAIR", CURSOR_CROSS_HAIR }, + { "CURSOR_BIN_DOWN", CURSOR_BIN_DOWN }, + { "CURSOR_LAMPPOST_DOWN", CURSOR_LAMPPOST_DOWN }, + { "CURSOR_FENCE_DOWN", CURSOR_FENCE_DOWN }, + { "CURSOR_FLOWER_DOWN", CURSOR_FLOWER_DOWN }, + { "CURSOR_PATH_DOWN", CURSOR_PATH_DOWN }, + { "CURSOR_DIG_DOWN", CURSOR_DIG_DOWN }, + { "CURSOR_WATER_DOWN", CURSOR_WATER_DOWN }, + { "CURSOR_HOUSE_DOWN", CURSOR_HOUSE_DOWN }, + { "CURSOR_VOLCANO_DOWN", CURSOR_VOLCANO_DOWN }, + { "CURSOR_WALK_DOWN", CURSOR_WALK_DOWN }, + { "CURSOR_PAINT_DOWN", CURSOR_PAINT_DOWN }, + { "CURSOR_ENTRANCE_DOWN", CURSOR_ENTRANCE_DOWN }, + { "CURSOR_HAND_OPEN", CURSOR_HAND_OPEN }, + { "CURSOR_HAND_CLOSED", CURSOR_HAND_CLOSED }, + { "CURSOR_ARROW", CURSOR_ARROW }, + }; + + auto result = LookupTable.find(s); + return (result != LookupTable.end()) ? + result->second : + defaultValue; + } + rct_object_entry ParseObjectEntry(const std::string & s) { rct_object_entry entry = { 0 }; @@ -117,17 +166,36 @@ namespace ObjectJsonHelpers auto objectsPath = env->GetDirectoryPath(DIRBASE::RCT2, DIRID::OBJECT); auto objectPath = Path::Combine(objectsPath, name); auto obj = ObjectFactory::CreateObjectFromLegacyFile(objectPath.c_str()); - auto &imgTable = static_cast(obj)->GetImageTable(); - auto numImages = imgTable.GetCount(); - auto images = imgTable.GetImages(); - for (uint32 i = start; i < Math::Min(numImages, end); i++) + if (obj != nullptr) { - auto g1 = images[i]; - auto length = g1_calculate_data_size(&g1); - g1.offset = Memory::Duplicate(g1.offset, length); - result.push_back(g1); + auto &imgTable = static_cast(obj)->GetImageTable(); + auto numImages = imgTable.GetCount(); + auto images = imgTable.GetImages(); + for (uint32 i = start; i < Math::Min(numImages, end); i++) + { + auto g1 = images[i]; + auto length = g1_calculate_data_size(&g1); + g1.offset = Memory::Duplicate(g1.offset, length); + result.push_back(g1); + } + delete obj; + } + else + { + log_warning("Unable to open '%s'", objectPath.c_str()); + } + + // Add place holders + auto placeHolders = (size_t)(end - start) - result.size(); + if (placeHolders > 0) + { + log_warning("Adding %d placeholders", placeHolders); + for (size_t i = 0; i < placeHolders; i++) + { + auto g1 = rct_g1_element{}; + result.push_back(g1); + } } - delete obj; return result; } diff --git a/src/openrct2/object/ObjectJsonHelpers.h b/src/openrct2/object/ObjectJsonHelpers.h index 7cc3c11cb7..28ac029f06 100644 --- a/src/openrct2/object/ObjectJsonHelpers.h +++ b/src/openrct2/object/ObjectJsonHelpers.h @@ -31,7 +31,9 @@ namespace ObjectJsonHelpers { bool GetBoolean(const json_t * obj, const std::string &name, bool defaultValue = false); std::string GetString(const json_t * value); + std::string GetString(const json_t * obj, const std::string &name, const std::string &defaultValue = ""); std::vector GetJsonStringArray(const json_t * arr); + uint8 ParseCursor(const std::string &s, uint8 defaultValue); rct_object_entry ParseObjectEntry(const std::string & s); void LoadStrings(const json_t * root, StringTable &stringTable); void LoadImages(const json_t * root, ImageTable &imageTable); diff --git a/src/openrct2/object/WallObject.cpp b/src/openrct2/object/WallObject.cpp index 4f1ad39de8..0212c7fb9a 100644 --- a/src/openrct2/object/WallObject.cpp +++ b/src/openrct2/object/WallObject.cpp @@ -15,10 +15,11 @@ #pragma endregion #include "../core/IStream.hpp" -#include "WallObject.h" - #include "../drawing/Drawing.h" +#include "../interface/Cursors.h" #include "../localisation/Language.h" +#include "ObjectJsonHelpers.h" +#include "WallObject.h" void WallObject::ReadLegacy(IReadObjectContext * context, IStream * stream) { @@ -88,3 +89,61 @@ void WallObject::DrawPreview(rct_drawpixelinfo * dpi, sint32 width, sint32 heigh gfx_draw_sprite(dpi, imageId, x, y, 0); } } + +void WallObject::ReadJson(IReadObjectContext * context, const json_t * root) +{ + auto properties = json_object_get(root, "properties"); + + _legacyType.wall.tool_id = ObjectJsonHelpers::ParseCursor(ObjectJsonHelpers::GetString(properties, "cursor"), CURSOR_FENCE_DOWN); + _legacyType.wall.height = json_integer_value(json_object_get(properties, "height")); + _legacyType.wall.price = json_integer_value(json_object_get(properties, "price")); + + auto jScrollingMode = json_object_get(properties, "scrollingMode"); + _legacyType.wall.scrolling_mode = jScrollingMode != nullptr ? + json_integer_value(jScrollingMode) : + -1; + + SetPrimarySceneryGroup(ObjectJsonHelpers::GetString(json_object_get(properties, "sceneryGroup"))); + + // Flags + _legacyType.wall.flags = ObjectJsonHelpers::GetFlags(properties, { + { "hasPrimaryColour", WALL_SCENERY_HAS_PRIMARY_COLOUR }, + { "hasSecondaryColour", WALL_SCENERY_HAS_SECONDARY_COLOUR }, + { "hasTernaryColour", WALL_SCENERY_HAS_TERNARY_COLOUR }, + { "hasGrass", WALL_SCENERY_HAS_GLASS }, + { "isBanner", WALL_SCENERY_IS_BANNER }, + { "isDoor", WALL_SCENERY_IS_DOOR }, + { "isLongDoorAnimation", WALL_SCENERY_LONG_DOOR_ANIMATION }}); + _legacyType.wall.flags2 = ObjectJsonHelpers::GetFlags(properties, { + { "isOpaque", WALL_SCENERY_2_IS_OPAQUE }, + { "isAnimated", WALL_SCENERY_2_ANIMATED }}); + + // HACK To avoid 'negated' properties in JSON, handle this separately until + // flag is inverted in this code base. + if (!ObjectJsonHelpers::GetBoolean(properties, "isAllowedOnSlope", false)) + { + _legacyType.wall.flags |= WALL_SCENERY_CANT_BUILD_ON_SLOPE; + } + + // HACK WALL_SCENERY_HAS_PRIMARY_COLOUR actually means, has any colour but we simplify the + // JSON and handle this on load. We should change code base in future to reflect the JSON. + if (!(_legacyType.wall.flags & WALL_SCENERY_HAS_PRIMARY_COLOUR)) + { + if ((_legacyType.wall.flags & WALL_SCENERY_HAS_SECONDARY_COLOUR) || + (_legacyType.wall.flags & WALL_SCENERY_HAS_TERNARY_COLOUR)) + { + _legacyType.wall.flags2 |= WALL_SCENERY_2_NO_SELECT_PRIMARY_COLOUR; + } + } + + // Door sound + auto jDoorSound = json_object_get(properties, "scrollingMode"); + if (jDoorSound != nullptr) + { + auto doorSound = json_integer_value(jDoorSound); + _legacyType.wall.flags2 |= (doorSound << WALL_SCENERY_2_DOOR_SOUND_SHIFT) & WALL_SCENERY_2_DOOR_SOUND_MASK; + } + + ObjectJsonHelpers::LoadStrings(root, GetStringTable()); + ObjectJsonHelpers::LoadImages(root, GetImageTable()); +} diff --git a/src/openrct2/object/WallObject.h b/src/openrct2/object/WallObject.h index 605443e0c0..388685f905 100644 --- a/src/openrct2/object/WallObject.h +++ b/src/openrct2/object/WallObject.h @@ -31,6 +31,7 @@ public: void * GetLegacyData() override { return &_legacyType; } void ReadLegacy(IReadObjectContext * context, IStream * stream) override; + void ReadJson(IReadObjectContext * context, const json_t * root) override; void Load() override; void Unload() override; From f11973f692f214dd5d9c9a6ddeb3cbc34159c98c Mon Sep 17 00:00:00 2001 From: Ted John Date: Sun, 17 Dec 2017 12:55:56 +0000 Subject: [PATCH 31/93] Fix typo, hasGrass -> hasGlass --- src/openrct2/object/WallObject.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/openrct2/object/WallObject.cpp b/src/openrct2/object/WallObject.cpp index 0212c7fb9a..4da70af90b 100644 --- a/src/openrct2/object/WallObject.cpp +++ b/src/openrct2/object/WallObject.cpp @@ -110,7 +110,7 @@ void WallObject::ReadJson(IReadObjectContext * context, const json_t * root) { "hasPrimaryColour", WALL_SCENERY_HAS_PRIMARY_COLOUR }, { "hasSecondaryColour", WALL_SCENERY_HAS_SECONDARY_COLOUR }, { "hasTernaryColour", WALL_SCENERY_HAS_TERNARY_COLOUR }, - { "hasGrass", WALL_SCENERY_HAS_GLASS }, + { "hasGlass", WALL_SCENERY_HAS_GLASS }, { "isBanner", WALL_SCENERY_IS_BANNER }, { "isDoor", WALL_SCENERY_IS_DOOR }, { "isLongDoorAnimation", WALL_SCENERY_LONG_DOOR_ANIMATION }}); From 7c05e22cd0deea592ae6ed4bf9ddec353957ac79 Mon Sep 17 00:00:00 2001 From: Ted John Date: Sun, 17 Dec 2017 16:35:03 +0000 Subject: [PATCH 32/93] Refactor large scenery tile flags field --- src/openrct2/paint/tile_element/LargeScenery.cpp | 6 +++--- src/openrct2/world/Map.cpp | 2 +- src/openrct2/world/Scenery.h | 11 +++++++++-- src/openrct2/world/Wall.cpp | 2 +- 4 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/openrct2/paint/tile_element/LargeScenery.cpp b/src/openrct2/paint/tile_element/LargeScenery.cpp index d5b2775eed..072bbe2a9e 100644 --- a/src/openrct2/paint/tile_element/LargeScenery.cpp +++ b/src/openrct2/paint/tile_element/LargeScenery.cpp @@ -39,7 +39,7 @@ static void large_scenery_paint_supports( uint32 dword_F4387C, rct_large_scenery_tile * tile) { - if (tile->var_7 & 0x20) { + if (tile->flags & LARGE_SCENERY_TILE_FLAG_NO_SUPPORTS) { return; } @@ -61,7 +61,7 @@ static void large_scenery_paint_supports( sint32 clearanceHeight = ceil2(tileElement->clearance_height * 8 + 15, 16); - if (tile->var_7 & 0x40) { + if (tile->flags & LARGE_SCENERY_TILE_FLAG_ALLOW_SUPPORTS_ABOVE) { paint_util_set_segment_support_height(session, SEGMENTS_ALL, clearanceHeight, 0x20); } else { paint_util_set_segment_support_height(session, SEGMENTS_ALL, 0xFFFF, 0); @@ -232,7 +232,7 @@ void large_scenery_paint(paint_session * session, uint8 direction, uint16 height ah = 0x80; } ah -= 3; - uint16 edi = tile->var_7; + uint16 edi = tile->flags; sint32 esi = 16; if (edi & 0xF00) { edi &= 0xF000; diff --git a/src/openrct2/world/Map.cpp b/src/openrct2/world/Map.cpp index 2c8307b5ba..7195a893df 100644 --- a/src/openrct2/world/Map.cpp +++ b/src/openrct2/world/Map.cpp @@ -2822,7 +2822,7 @@ void game_command_place_large_scenery(sint32* eax, sint32* ebx, sint32* ecx, sin sint32 zLow = (tile->z_offset + maxHeight) / 8; sint32 zHigh = (tile->z_clearance / 8) + zLow; - sint32 bx = tile->var_7 >> 12; + sint32 bx = tile->flags >> 12; bx <<= rotation; uint8 bl = bx; uint8 bh = bl >> 4; diff --git a/src/openrct2/world/Scenery.h b/src/openrct2/world/Scenery.h index f61bed122b..312343db94 100644 --- a/src/openrct2/world/Scenery.h +++ b/src/openrct2/world/Scenery.h @@ -56,15 +56,22 @@ struct rct_large_scenery_tile { sint16 y_offset; sint16 z_offset; uint8 z_clearance; - uint16 var_7; + // CCCC WWWW 0SS0 0000 + uint16 flags; }; assert_struct_size(rct_large_scenery_tile, 9); +enum +{ + LARGE_SCENERY_TILE_FLAG_NO_SUPPORTS = 0x20, + LARGE_SCENERY_TILE_FLAG_ALLOW_SUPPORTS_ABOVE = 0x40, +}; + struct rct_large_scenery_text_glyph { uint8 image_offset; uint8 width; uint8 height; - uint8 var_3; + uint8 pad_3; }; assert_struct_size(rct_large_scenery_text_glyph, 4); diff --git a/src/openrct2/world/Wall.cpp b/src/openrct2/world/Wall.cpp index 73255989a9..bfc911dc74 100644 --- a/src/openrct2/world/Wall.cpp +++ b/src/openrct2/world/Wall.cpp @@ -222,7 +222,7 @@ static bool WallCheckObstruction(rct_scenery_entry * wall, tile = &entry->large_scenery.tiles[sequence]; { sint32 direction = ((edge - tile_element_get_direction(tileElement)) & TILE_ELEMENT_DIRECTION_MASK) + 8; - if (!(tile->var_7 & (1 << direction))) + if (!(tile->flags & (1 << direction))) { map_obstruction_set_error_text(tileElement); return false; From 1e3ce8754e052f0f5b867737cbc9f12ad8396478 Mon Sep 17 00:00:00 2001 From: Ted John Date: Sun, 17 Dec 2017 17:00:45 +0000 Subject: [PATCH 33/93] Add JSON loading for large scenery --- src/openrct2/object/LargeSceneryObject.cpp | 81 +++++++++++++++++++++- src/openrct2/object/LargeSceneryObject.h | 3 + src/openrct2/object/ObjectFactory.cpp | 1 + 3 files changed, 83 insertions(+), 2 deletions(-) diff --git a/src/openrct2/object/LargeSceneryObject.cpp b/src/openrct2/object/LargeSceneryObject.cpp index 6dee19c775..9e0507ec02 100644 --- a/src/openrct2/object/LargeSceneryObject.cpp +++ b/src/openrct2/object/LargeSceneryObject.cpp @@ -14,12 +14,15 @@ *****************************************************************************/ #pragma endregion +#pragma warning(disable : 4706) // assignment within conditional expression + #include "../core/IStream.hpp" #include "../core/Memory.hpp" -#include "LargeSceneryObject.h" - #include "../drawing/Drawing.h" +#include "../interface/Cursors.h" #include "../localisation/Language.h" +#include "LargeSceneryObject.h" +#include "ObjectJsonHelpers.h" void LargeSceneryObject::ReadLegacy(IReadObjectContext * context, IStream * stream) { @@ -118,3 +121,77 @@ std::vector LargeSceneryObject::ReadTiles(IStream * stre tiles.push_back({ -1, -1, -1, 255, 0xFFFF }); return tiles; } + +void LargeSceneryObject::ReadJson(IReadObjectContext * context, const json_t * root) +{ + auto properties = json_object_get(root, "properties"); + + _legacyType.large_scenery.tool_id = ObjectJsonHelpers::ParseCursor(ObjectJsonHelpers::GetString(properties, "cursor"), CURSOR_STATUE_DOWN); + _legacyType.large_scenery.price = json_integer_value(json_object_get(properties, "price")); + _legacyType.large_scenery.removal_price = json_integer_value(json_object_get(properties, "height")); + + auto jScrollingMode = json_object_get(properties, "scrollingMode"); + _legacyType.large_scenery.scrolling_mode = jScrollingMode != nullptr ? + json_integer_value(jScrollingMode) : + -1; + + // Flags + _legacyType.large_scenery.flags = ObjectJsonHelpers::GetFlags(properties, { + { "hasPrimaryColour", LARGE_SCENERY_FLAG_HAS_PRIMARY_COLOUR }, + { "hasSecondaryColour", LARGE_SCENERY_FLAG_HAS_SECONDARY_COLOUR }, + { "isAnimated", LARGE_SCENERY_FLAG_ANIMATED }, + { "isPhotogenic", LARGE_SCENERY_FLAG_PHOTOGENIC } }); + + // Tiles + auto jTiles = json_object_get(properties, "tiles"); + if (jTiles != nullptr) + { + _tiles = ReadJsonTiles(jTiles); + } + + // Read text + auto j3dFont = json_object_get(properties, "3dFont"); + if (j3dFont != nullptr) + { + _3dFont = ReadJson3dFont(j3dFont); + _legacyType.large_scenery.flags |= LARGE_SCENERY_FLAG_3D_TEXT; + } + + SetPrimarySceneryGroup(ObjectJsonHelpers::GetString(json_object_get(properties, "sceneryGroup"))); + + ObjectJsonHelpers::LoadStrings(root, GetStringTable()); + ObjectJsonHelpers::LoadImages(root, GetImageTable()); +} + +std::vector LargeSceneryObject::ReadJsonTiles(const json_t * jTiles) +{ + std::vector tiles; + size_t index; + const json_t * jTile; + json_array_foreach(jTiles, index, jTile) + { + rct_large_scenery_tile tile = { 0 }; + tile.x_offset = json_integer_value(json_object_get(jTile, "x")); + tile.y_offset = json_integer_value(json_object_get(jTile, "y")); + tile.z_offset = json_integer_value(json_object_get(jTile, "z")); + tile.z_clearance = json_integer_value(json_object_get(jTile, "clearance")); + if (!ObjectJsonHelpers::GetBoolean(jTile, "hasSupports")) + { + tile.flags |= LARGE_SCENERY_TILE_FLAG_NO_SUPPORTS; + } + if (ObjectJsonHelpers::GetBoolean(jTile, "allowSupportsAbove")) + { + tile.flags |= LARGE_SCENERY_TILE_FLAG_ALLOW_SUPPORTS_ABOVE; + } + tile.flags |= (json_integer_value(json_object_get(jTile, "corners")) & 0xFF) << 8; + tile.flags |= (json_integer_value(json_object_get(jTile, "walls")) & 0xFF) << 12; + tiles.push_back(tile); + } + return tiles; +} + +std::unique_ptr LargeSceneryObject::ReadJson3dFont(const json_t * j3dText) +{ + // TODO + return std::make_unique(); +} diff --git a/src/openrct2/object/LargeSceneryObject.h b/src/openrct2/object/LargeSceneryObject.h index e28eb5d1a3..3d60f0333e 100644 --- a/src/openrct2/object/LargeSceneryObject.h +++ b/src/openrct2/object/LargeSceneryObject.h @@ -35,6 +35,7 @@ public: void * GetLegacyData() override { return &_legacyType; } void ReadLegacy(IReadObjectContext * context, IStream * stream) override; + void ReadJson(IReadObjectContext * context, const json_t * root) override; void Load() override; void Unload() override; @@ -42,4 +43,6 @@ public: private: static std::vector ReadTiles(IStream * stream); + static std::vector ReadJsonTiles(const json_t * jTiles); + static std::unique_ptr ReadJson3dFont(const json_t * j3dFont); }; diff --git a/src/openrct2/object/ObjectFactory.cpp b/src/openrct2/object/ObjectFactory.cpp index 48fd44d35b..412f82c283 100644 --- a/src/openrct2/object/ObjectFactory.cpp +++ b/src/openrct2/object/ObjectFactory.cpp @@ -211,6 +211,7 @@ namespace ObjectFactory if (s == "footpath") return OBJECT_TYPE_PATHS; if (s == "footpath_banner") return OBJECT_TYPE_BANNERS; if (s == "footpath_item") return OBJECT_TYPE_PATH_BITS; + if (s == "scenery_large") return OBJECT_TYPE_LARGE_SCENERY; if (s == "scenery_wall") return OBJECT_TYPE_WALLS; if (s == "scenery_group") return OBJECT_TYPE_SCENERY_GROUP; if (s == "park_entrance") return OBJECT_TYPE_PARK_ENTRANCE; From 1668374d2cdb1b06038ffc7a0f32ab9bfe1e7e62 Mon Sep 17 00:00:00 2001 From: Ted John Date: Tue, 19 Dec 2017 10:26:20 +0000 Subject: [PATCH 34/93] Fix loading of JSON large scenery tiles --- src/openrct2/object/LargeSceneryObject.cpp | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/openrct2/object/LargeSceneryObject.cpp b/src/openrct2/object/LargeSceneryObject.cpp index 9e0507ec02..f8c53da10d 100644 --- a/src/openrct2/object/LargeSceneryObject.cpp +++ b/src/openrct2/object/LargeSceneryObject.cpp @@ -183,10 +183,26 @@ std::vector LargeSceneryObject::ReadJsonTiles(const json { tile.flags |= LARGE_SCENERY_TILE_FLAG_ALLOW_SUPPORTS_ABOVE; } - tile.flags |= (json_integer_value(json_object_get(jTile, "corners")) & 0xFF) << 8; - tile.flags |= (json_integer_value(json_object_get(jTile, "walls")) & 0xFF) << 12; + + // All corners are by default occupied + auto jCorners = json_object_get(jTile, "corners"); + auto corners = 0xF; + if (jCorners != nullptr) + { + corners = json_integer_value(jCorners); + } + tile.flags |= (corners & 0xFF) << 12; + + auto walls = json_integer_value(json_object_get(jTile, "walls")); + tile.flags |= (walls & 0xFF) << 8; + tiles.push_back(tile); } + + // HACK Add end of tiles marker + // We should remove this later by improving the code base to use tiles array length + tiles.push_back({ -1, -1, -1, 0xFF, 0xFFFF }); + return tiles; } From 44e2f1d57786c9a798e8913ff10bdf817d77a9f5 Mon Sep 17 00:00:00 2001 From: Ted John Date: Tue, 19 Dec 2017 11:31:35 +0000 Subject: [PATCH 35/93] Add JSON loading for 3D fonts in large scenery --- src/openrct2/object/LargeSceneryObject.cpp | 67 ++++++++++++++++++++-- src/openrct2/object/LargeSceneryObject.h | 2 + src/openrct2/world/Scenery.h | 2 +- 3 files changed, 65 insertions(+), 6 deletions(-) diff --git a/src/openrct2/object/LargeSceneryObject.cpp b/src/openrct2/object/LargeSceneryObject.cpp index f8c53da10d..2cdee4e975 100644 --- a/src/openrct2/object/LargeSceneryObject.cpp +++ b/src/openrct2/object/LargeSceneryObject.cpp @@ -16,8 +16,10 @@ #pragma warning(disable : 4706) // assignment within conditional expression +#include #include "../core/IStream.hpp" #include "../core/Memory.hpp" +#include "../core/Util.hpp" #include "../drawing/Drawing.h" #include "../interface/Cursors.h" #include "../localisation/Language.h" @@ -82,12 +84,13 @@ void LargeSceneryObject::Load() _legacyType.large_scenery.text_image = _legacyType.image; if (_3dFont->flags & LARGE_SCENERY_TEXT_FLAG_VERTICAL) { - _legacyType.image += _3dFont->var_D * 2; + _legacyType.image += _3dFont->num_images * 2; } else { - _legacyType.image += _3dFont->var_D * 4; + _legacyType.image += _3dFont->num_images * 4; } + _legacyType.large_scenery.text = _3dFont.get(); } } @@ -206,8 +209,62 @@ std::vector LargeSceneryObject::ReadJsonTiles(const json return tiles; } -std::unique_ptr LargeSceneryObject::ReadJson3dFont(const json_t * j3dText) +std::unique_ptr LargeSceneryObject::ReadJson3dFont(const json_t * j3dFont) { - // TODO - return std::make_unique(); + auto font = std::make_unique(); + + auto jOffsets = json_object_get(j3dFont, "offsets"); + if (jOffsets != nullptr) + { + auto offsets = ReadJsonOffsets(jOffsets); + auto numOffsets = std::min(Util::CountOf(font->offset), offsets.size()); + std::copy_n(offsets.data(), numOffsets, font->offset); + } + + font->max_width = json_integer_value(json_object_get(j3dFont, "maxWidth")); + font->num_images = json_integer_value(json_object_get(j3dFont, "numImages")); + font->flags = ObjectJsonHelpers::GetFlags(j3dFont, { + { "isVertical", LARGE_SCENERY_TEXT_FLAG_VERTICAL }, + { "isTwoLine", LARGE_SCENERY_TEXT_FLAG_TWO_LINE } }); + + auto jGlyphs = json_object_get(j3dFont, "glyphs"); + if (jGlyphs != nullptr) + { + auto glyphs = ReadJsonGlyphs(jGlyphs); + auto numGlyphs = std::min(Util::CountOf(font->glyphs), glyphs.size()); + std::copy_n(glyphs.data(), numGlyphs, font->glyphs); + } + + return font; +} + +std::vector LargeSceneryObject::ReadJsonOffsets(const json_t * jOffsets) +{ + std::vector offsets; + size_t index; + const json_t * jOffset; + json_array_foreach(jOffsets, index, jOffset) + { + LocationXY16 offset = { 0 }; + offset.x = json_integer_value(json_object_get(jOffset, "x")); + offset.y = json_integer_value(json_object_get(jOffset, "y")); + offsets.push_back(offset); + } + return offsets; +} + +std::vector LargeSceneryObject::ReadJsonGlyphs(const json_t * jGlpyhs) +{ + std::vector glyphs; + size_t index; + const json_t * jGlyph; + json_array_foreach(jGlpyhs, index, jGlyph) + { + rct_large_scenery_text_glyph glyph; + glyph.image_offset = json_integer_value(json_object_get(jGlyph, "image")); + glyph.width = json_integer_value(json_object_get(jGlyph, "width")); + glyph.height = json_integer_value(json_object_get(jGlyph, "height")); + glyphs.push_back(glyph); + } + return glyphs; } diff --git a/src/openrct2/object/LargeSceneryObject.h b/src/openrct2/object/LargeSceneryObject.h index 3d60f0333e..27d6a232df 100644 --- a/src/openrct2/object/LargeSceneryObject.h +++ b/src/openrct2/object/LargeSceneryObject.h @@ -45,4 +45,6 @@ private: static std::vector ReadTiles(IStream * stream); static std::vector ReadJsonTiles(const json_t * jTiles); static std::unique_ptr ReadJson3dFont(const json_t * j3dFont); + static std::vector ReadJsonOffsets(const json_t * jOffsets); + static std::vector ReadJsonGlyphs(const json_t * jGlpyhs); }; diff --git a/src/openrct2/world/Scenery.h b/src/openrct2/world/Scenery.h index 312343db94..afd723e395 100644 --- a/src/openrct2/world/Scenery.h +++ b/src/openrct2/world/Scenery.h @@ -80,7 +80,7 @@ struct rct_large_scenery_text { uint16 max_width; // 0x8 uint16 pad_A; // 0xA uint8 flags; // 0xC - uint8 var_D; // 0xD + uint8 num_images; // 0xD rct_large_scenery_text_glyph glyphs[256]; // 0xE }; assert_struct_size(rct_large_scenery_text, 14 + 4 * 256); From 7d26492961c956b676a0aec94aba6279237c1e8f Mon Sep 17 00:00:00 2001 From: Ted John Date: Tue, 19 Dec 2017 12:32:02 +0000 Subject: [PATCH 36/93] Fix removal price for large scenery --- src/openrct2/object/LargeSceneryObject.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/openrct2/object/LargeSceneryObject.cpp b/src/openrct2/object/LargeSceneryObject.cpp index 2cdee4e975..cff381489c 100644 --- a/src/openrct2/object/LargeSceneryObject.cpp +++ b/src/openrct2/object/LargeSceneryObject.cpp @@ -131,7 +131,7 @@ void LargeSceneryObject::ReadJson(IReadObjectContext * context, const json_t * r _legacyType.large_scenery.tool_id = ObjectJsonHelpers::ParseCursor(ObjectJsonHelpers::GetString(properties, "cursor"), CURSOR_STATUE_DOWN); _legacyType.large_scenery.price = json_integer_value(json_object_get(properties, "price")); - _legacyType.large_scenery.removal_price = json_integer_value(json_object_get(properties, "height")); + _legacyType.large_scenery.removal_price = json_integer_value(json_object_get(properties, "removalPrice")); auto jScrollingMode = json_object_get(properties, "scrollingMode"); _legacyType.large_scenery.scrolling_mode = jScrollingMode != nullptr ? From a03b58501bba8486a7fee351e389e6bd4fa9804c Mon Sep 17 00:00:00 2001 From: Ted John Date: Tue, 19 Dec 2017 15:08:48 +0000 Subject: [PATCH 37/93] Add JSON loading for small scenery --- src/openrct2/object/ObjectFactory.cpp | 1 + src/openrct2/object/SmallSceneryObject.cpp | 74 +++++++++++++++++++++- src/openrct2/object/SmallSceneryObject.h | 2 + 3 files changed, 75 insertions(+), 2 deletions(-) diff --git a/src/openrct2/object/ObjectFactory.cpp b/src/openrct2/object/ObjectFactory.cpp index 412f82c283..a399fe5b1b 100644 --- a/src/openrct2/object/ObjectFactory.cpp +++ b/src/openrct2/object/ObjectFactory.cpp @@ -211,6 +211,7 @@ namespace ObjectFactory if (s == "footpath") return OBJECT_TYPE_PATHS; if (s == "footpath_banner") return OBJECT_TYPE_BANNERS; if (s == "footpath_item") return OBJECT_TYPE_PATH_BITS; + if (s == "scenery_small") return OBJECT_TYPE_SMALL_SCENERY; if (s == "scenery_large") return OBJECT_TYPE_LARGE_SCENERY; if (s == "scenery_wall") return OBJECT_TYPE_WALLS; if (s == "scenery_group") return OBJECT_TYPE_SCENERY_GROUP; diff --git a/src/openrct2/object/SmallSceneryObject.cpp b/src/openrct2/object/SmallSceneryObject.cpp index 24a2e43bec..ed60b7c1c0 100644 --- a/src/openrct2/object/SmallSceneryObject.cpp +++ b/src/openrct2/object/SmallSceneryObject.cpp @@ -14,16 +14,19 @@ *****************************************************************************/ #pragma endregion +#pragma warning(disable : 4706) // assignment within conditional expression + #include "../core/IStream.hpp" #include "../core/Math.hpp" #include "../core/Memory.hpp" #include "../core/String.hpp" -#include "SmallSceneryObject.h" - #include "../drawing/Drawing.h" +#include "../interface/Cursors.h" #include "../localisation/Language.h" #include "../world/Scenery.h" #include "../world/SmallScenery.h" +#include "SmallSceneryObject.h" +#include "ObjectJsonHelpers.h" void SmallSceneryObject::ReadLegacy(IReadObjectContext * context, IStream * stream) { @@ -231,3 +234,70 @@ rct_object_entry SmallSceneryObject::GetScgAbstrHeader() { return Object::CreateHeader("SCGABSTR", 207140231, 932253451); } + +void SmallSceneryObject::ReadJson(IReadObjectContext * context, const json_t * root) +{ + auto properties = json_object_get(root, "properties"); + + _legacyType.small_scenery.height = json_integer_value(json_object_get(properties, "height")); + _legacyType.small_scenery.tool_id = ObjectJsonHelpers::ParseCursor(ObjectJsonHelpers::GetString(properties, "cursor"), CURSOR_STATUE_DOWN); + _legacyType.small_scenery.price = json_integer_value(json_object_get(properties, "price")); + _legacyType.small_scenery.removal_price = json_integer_value(json_object_get(properties, "removalPrice")); + _legacyType.small_scenery.animation_delay = json_integer_value(json_object_get(properties, "animationDelay")); + _legacyType.small_scenery.animation_mask = json_integer_value(json_object_get(properties, "animationMask")); + _legacyType.small_scenery.num_frames = json_integer_value(json_object_get(properties, "numFrames")); + + // Flags + _legacyType.small_scenery.flags = ObjectJsonHelpers::GetFlags(properties, { + { "isFullTile", SMALL_SCENERY_FLAG_FULL_TILE }, + { "SMALL_SCENERY_FLAG_VOFFSET_CENTRE", SMALL_SCENERY_FLAG_VOFFSET_CENTRE }, + { "requiresFlatSurface", SMALL_SCENERY_FLAG_REQUIRE_FLAT_SURFACE }, + { "isRotatable", SMALL_SCENERY_FLAG_ROTATABLE }, + { "isAnimated", SMALL_SCENERY_FLAG_ANIMATED }, + { "canWither", SMALL_SCENERY_FLAG_CAN_WITHER }, + { "canBeWatered", SMALL_SCENERY_FLAG_CAN_BE_WATERED }, + { "hasOverlayImage", SMALL_SCENERY_FLAG_ANIMATED_FG }, + { "SMALL_SCENERY_FLAG_DIAGONAL", SMALL_SCENERY_FLAG_DIAGONAL }, + { "hasGlass", SMALL_SCENERY_FLAG_HAS_GLASS }, + { "hasPrimaryColour", SMALL_SCENERY_FLAG_HAS_PRIMARY_COLOUR }, + { "SMALL_SCENERY_FLAG_FOUNTAIN_SPRAY_1", SMALL_SCENERY_FLAG_FOUNTAIN_SPRAY_1 }, + { "SMALL_SCENERY_FLAG_FOUNTAIN_SPRAY_4", SMALL_SCENERY_FLAG_FOUNTAIN_SPRAY_4 }, + { "isClock", SMALL_SCENERY_FLAG_IS_CLOCK }, + { "SMALL_SCENERY_FLAG_SWAMP_GOO", SMALL_SCENERY_FLAG_SWAMP_GOO }, + { "SMALL_SCENERY_FLAG17", SMALL_SCENERY_FLAG17 }, + { "isStackable", SMALL_SCENERY_FLAG_STACKABLE }, + { "prohibitWalls", SMALL_SCENERY_FLAG_NO_WALLS }, + { "hasSecondaryColour", SMALL_SCENERY_FLAG_HAS_SECONDARY_COLOUR }, + { "hasNoSupports", SMALL_SCENERY_FLAG_NO_SUPPORTS }, + { "SMALL_SCENERY_FLAG_VISIBLE_WHEN_ZOOMED", SMALL_SCENERY_FLAG_VISIBLE_WHEN_ZOOMED }, + { "SMALL_SCENERY_FLAG_COG", SMALL_SCENERY_FLAG_COG }, + { "allowSupportsAbove", SMALL_SCENERY_FLAG_BUILD_DIRECTLY_ONTOP }, + { "SMALL_SCENERY_FLAG_HALF_SPACE", SMALL_SCENERY_FLAG_HALF_SPACE }, + { "SMALL_SCENERY_FLAG_THREE_QUARTERS", SMALL_SCENERY_FLAG_THREE_QUARTERS }, + { "supportsHavePrimaryColour", SMALL_SCENERY_FLAG_PAINT_SUPPORTS }, + { "SMALL_SCENERY_FLAG27", SMALL_SCENERY_FLAG27 } }); + + auto jFrameOffsets = json_object_get(properties, "frameOffsets"); + if (jFrameOffsets != nullptr) + { + _frameOffsets = ReadJsonFrameOffsets(jFrameOffsets); + _legacyType.small_scenery.flags |= SMALL_SCENERY_FLAG_HAS_FRAME_OFFSETS; + } + + SetPrimarySceneryGroup(ObjectJsonHelpers::GetString(json_object_get(properties, "sceneryGroup"))); + + ObjectJsonHelpers::LoadStrings(root, GetStringTable()); + ObjectJsonHelpers::LoadImages(root, GetImageTable()); +} + +std::vector SmallSceneryObject::ReadJsonFrameOffsets(const json_t * jFrameOffsets) +{ + std::vector offsets; + size_t index; + const json_t * jOffset; + json_array_foreach(jFrameOffsets, index, jOffset) + { + offsets.push_back(json_integer_value(jOffset)); + } + return offsets; +} diff --git a/src/openrct2/object/SmallSceneryObject.h b/src/openrct2/object/SmallSceneryObject.h index d7cbe04031..15043e6e9c 100644 --- a/src/openrct2/object/SmallSceneryObject.h +++ b/src/openrct2/object/SmallSceneryObject.h @@ -32,6 +32,7 @@ public: void * GetLegacyData() override { return &_legacyType; } void ReadLegacy(IReadObjectContext * context, IStream * stream) override; + void ReadJson(IReadObjectContext * context, const json_t * root) override; void Load() override; void Unload() override; @@ -39,6 +40,7 @@ public: private: static std::vector ReadFrameOffsets(IStream * stream); + static std::vector ReadJsonFrameOffsets(const json_t * jFrameOffsets); void PerformFixes(); rct_object_entry GetScgPiratHeader(); rct_object_entry GetScgMineHeader(); From 85f9f3ad098da09abd4c9e3332f9ba81416db1d6 Mon Sep 17 00:00:00 2001 From: Ted John Date: Tue, 19 Dec 2017 21:05:19 +0000 Subject: [PATCH 38/93] Read a shape property instead of individual flags --- src/openrct2/object/SmallSceneryObject.cpp | 30 +++++++++++++++++++--- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/src/openrct2/object/SmallSceneryObject.cpp b/src/openrct2/object/SmallSceneryObject.cpp index ed60b7c1c0..17b0ef2d1f 100644 --- a/src/openrct2/object/SmallSceneryObject.cpp +++ b/src/openrct2/object/SmallSceneryObject.cpp @@ -249,7 +249,6 @@ void SmallSceneryObject::ReadJson(IReadObjectContext * context, const json_t * r // Flags _legacyType.small_scenery.flags = ObjectJsonHelpers::GetFlags(properties, { - { "isFullTile", SMALL_SCENERY_FLAG_FULL_TILE }, { "SMALL_SCENERY_FLAG_VOFFSET_CENTRE", SMALL_SCENERY_FLAG_VOFFSET_CENTRE }, { "requiresFlatSurface", SMALL_SCENERY_FLAG_REQUIRE_FLAT_SURFACE }, { "isRotatable", SMALL_SCENERY_FLAG_ROTATABLE }, @@ -257,7 +256,6 @@ void SmallSceneryObject::ReadJson(IReadObjectContext * context, const json_t * r { "canWither", SMALL_SCENERY_FLAG_CAN_WITHER }, { "canBeWatered", SMALL_SCENERY_FLAG_CAN_BE_WATERED }, { "hasOverlayImage", SMALL_SCENERY_FLAG_ANIMATED_FG }, - { "SMALL_SCENERY_FLAG_DIAGONAL", SMALL_SCENERY_FLAG_DIAGONAL }, { "hasGlass", SMALL_SCENERY_FLAG_HAS_GLASS }, { "hasPrimaryColour", SMALL_SCENERY_FLAG_HAS_PRIMARY_COLOUR }, { "SMALL_SCENERY_FLAG_FOUNTAIN_SPRAY_1", SMALL_SCENERY_FLAG_FOUNTAIN_SPRAY_1 }, @@ -272,11 +270,35 @@ void SmallSceneryObject::ReadJson(IReadObjectContext * context, const json_t * r { "SMALL_SCENERY_FLAG_VISIBLE_WHEN_ZOOMED", SMALL_SCENERY_FLAG_VISIBLE_WHEN_ZOOMED }, { "SMALL_SCENERY_FLAG_COG", SMALL_SCENERY_FLAG_COG }, { "allowSupportsAbove", SMALL_SCENERY_FLAG_BUILD_DIRECTLY_ONTOP }, - { "SMALL_SCENERY_FLAG_HALF_SPACE", SMALL_SCENERY_FLAG_HALF_SPACE }, - { "SMALL_SCENERY_FLAG_THREE_QUARTERS", SMALL_SCENERY_FLAG_THREE_QUARTERS }, { "supportsHavePrimaryColour", SMALL_SCENERY_FLAG_PAINT_SUPPORTS }, { "SMALL_SCENERY_FLAG27", SMALL_SCENERY_FLAG27 } }); + // Determine shape flags from a shape string + auto shape = ObjectJsonHelpers::GetString(properties, "shape"); + if (!shape.empty()) + { + auto quarters = shape.substr(0, 3); + if (quarters == "2/4") + { + _legacyType.small_scenery.flags |= SMALL_SCENERY_FLAG_FULL_TILE | SMALL_SCENERY_FLAG_HALF_SPACE; + } + else if (quarters == "3/4") + { + _legacyType.small_scenery.flags |= SMALL_SCENERY_FLAG_FULL_TILE | SMALL_SCENERY_FLAG_THREE_QUARTERS; + } + else if (quarters == "4/4") + { + _legacyType.small_scenery.flags |= SMALL_SCENERY_FLAG_FULL_TILE; + } + if (shape.size() >= 5) + { + if ((shape.substr(3) == "+D")) + { + _legacyType.small_scenery.flags |= SMALL_SCENERY_FLAG_DIAGONAL; + } + } + } + auto jFrameOffsets = json_object_get(properties, "frameOffsets"); if (jFrameOffsets != nullptr) { From 01067eebad19771b114d7472149763d8626914fd Mon Sep 17 00:00:00 2001 From: Ted John Date: Wed, 20 Dec 2017 16:30:02 +0000 Subject: [PATCH 39/93] Revert 287d97a8937eb4985da060063f09816291219b78 Caused all food stalls to incorrectly have colour tab. --- src/openrct2/ride/RideData.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/openrct2/ride/RideData.cpp b/src/openrct2/ride/RideData.cpp index 6305f9c05e..df604d8573 100644 --- a/src/openrct2/ride/RideData.cpp +++ b/src/openrct2/ride/RideData.cpp @@ -1538,7 +1538,7 @@ const uint32 ShopItemImage[SHOP_ITEM_COUNT] = { SPR_SHOP_ITEM_DRINK, SPR_SHOP_ITEM_BURGER, SPR_SHOP_ITEM_CHIPS, - SPR_CSG_ICE_CREAM_STALL_BEGIN + 3, + SPR_SHOP_ITEM_ICE_CREAM, SPR_SHOP_ITEM_CANDYFLOSS, SPR_SHOP_ITEM_EMPTY_CAN, SPR_SHOP_ITEM_RUBBISH, @@ -2092,7 +2092,7 @@ const rct_ride_properties RideProperties[RIDE_TYPE_COUNT] = { RIDE_TYPE_FLAG_HAS_LOAD_OPTIONS | RIDE_TYPE_FLAG_HAS_NO_TRACK | RIDE_TYPE_FLAG_16 | RIDE_TYPE_FLAG_TRACK_NO_WALLS | RIDE_TYPE_FLAG_FLAT_RIDE | RIDE_TYPE_FLAG_HAS_VEHICLE_COLOURS, 7, 15, 0, 0, 0, 0 }, // RIDE_TYPE_SWINGING_INVERTER_SHIP - {RIDE_TYPE_FLAG_HAS_TRACK_COLOUR_MAIN | RIDE_TYPE_FLAG_3 | RIDE_TYPE_FLAG_CANNOT_HAVE_GAPS | RIDE_TYPE_FLAG_NO_TEST_MODE | RIDE_TYPE_FLAG_NO_VEHICLES | + {RIDE_TYPE_FLAG_3 | RIDE_TYPE_FLAG_CANNOT_HAVE_GAPS | RIDE_TYPE_FLAG_NO_TEST_MODE | RIDE_TYPE_FLAG_NO_VEHICLES | RIDE_TYPE_FLAG_HAS_NO_TRACK | RIDE_TYPE_FLAG_IS_SHOP | RIDE_TYPE_FLAG_TRACK_NO_WALLS | RIDE_TYPE_FLAG_FLAT_RIDE | RIDE_TYPE_FLAG_SELLS_FOOD, 0, 0, 0, 0, 0, 0 }, // RIDE_TYPE_FOOD_STALL From afbdb6dfc7c001d0ec0a9be21b81c1de25f9ce88 Mon Sep 17 00:00:00 2001 From: Ted John Date: Wed, 20 Dec 2017 16:31:06 +0000 Subject: [PATCH 40/93] Continue work on ride JSON loading --- src/openrct2/object/ObjectJsonHelpers.cpp | 44 +++++ src/openrct2/object/ObjectJsonHelpers.h | 3 + src/openrct2/object/RideObject.cpp | 219 ++++++++++++++++++---- src/openrct2/object/RideObject.h | 13 +- 4 files changed, 239 insertions(+), 40 deletions(-) diff --git a/src/openrct2/object/ObjectJsonHelpers.cpp b/src/openrct2/object/ObjectJsonHelpers.cpp index e8519e7885..c3e3a4148e 100644 --- a/src/openrct2/object/ObjectJsonHelpers.cpp +++ b/src/openrct2/object/ObjectJsonHelpers.cpp @@ -57,12 +57,36 @@ namespace ObjectJsonHelpers defaultValue; } + sint32 GetInteger(const json_t * obj, const std::string &name, const sint32 &defaultValue) + { + auto value = json_object_get(obj, name.c_str()); + if (json_is_integer(value)) + { + sint64 val = json_integer_value(value); + if (val >= std::numeric_limits::min() && + val <= std::numeric_limits::max()) + { + return static_cast(val); + } + } + return defaultValue; + } + + float GetFloat(const json_t * obj, const std::string &name, const float &defaultValue) + { + auto value = json_object_get(obj, name.c_str()); + return json_is_number(value) ? + json_number_value(value) : + defaultValue; + } + std::vector GetJsonStringArray(const json_t * arr) { std::vector result; if (json_is_array(arr)) { auto count = json_array_size(arr); + result.reserve(count); for (size_t i = 0; i < count; i++) { auto element = json_string_value(json_array_get(arr, i)); @@ -76,6 +100,26 @@ namespace ObjectJsonHelpers return result; } + std::vector GetJsonIntegerArray(const json_t * arr) + { + std::vector result; + if (json_is_array(arr)) + { + auto count = json_array_size(arr); + result.reserve(count); + for (size_t i = 0; i < count; i++) + { + auto element = json_integer_value(json_array_get(arr, i)); + result.push_back(element); + } + } + else if (json_is_integer(arr)) + { + result.push_back(json_integer_value(arr)); + } + return result; + } + uint8 ParseCursor(const std::string &s, uint8 defaultValue) { static const std::unordered_map LookupTable diff --git a/src/openrct2/object/ObjectJsonHelpers.h b/src/openrct2/object/ObjectJsonHelpers.h index 28ac029f06..ae13934ba0 100644 --- a/src/openrct2/object/ObjectJsonHelpers.h +++ b/src/openrct2/object/ObjectJsonHelpers.h @@ -32,7 +32,10 @@ namespace ObjectJsonHelpers bool GetBoolean(const json_t * obj, const std::string &name, bool defaultValue = false); std::string GetString(const json_t * value); std::string GetString(const json_t * obj, const std::string &name, const std::string &defaultValue = ""); + sint32 GetInteger(const json_t * obj, const std::string &name, const sint32 &defaultValue = 0); + float GetFloat(const json_t * obj, const std::string &name, const float &defaultValue = 0); std::vector GetJsonStringArray(const json_t * arr); + std::vector GetJsonIntegerArray(const json_t * arr); uint8 ParseCursor(const std::string &s, uint8 defaultValue); rct_object_entry ParseObjectEntry(const std::string & s); void LoadStrings(const json_t * root, StringTable &stringTable); diff --git a/src/openrct2/object/RideObject.cpp b/src/openrct2/object/RideObject.cpp index 926dc1ac1d..385ea40e24 100644 --- a/src/openrct2/object/RideObject.cpp +++ b/src/openrct2/object/RideObject.cpp @@ -14,6 +14,8 @@ *****************************************************************************/ #pragma endregion +#pragma warning(disable : 4706) // assignment within conditional expression + #include #include #include "../core/IStream.hpp" @@ -541,7 +543,183 @@ uint8 RideObject::CalculateNumHorizontalFrames(const rct_ride_entry_vehicle * ve return numHorizontalFrames; } -static uint8 ParseRideType(const std::string &s) +void RideObject::ReadJson(IReadObjectContext * context, const json_t * root) +{ + auto properties = json_object_get(root, "properties"); + + auto rideTypes = ObjectJsonHelpers::GetJsonStringArray(json_object_get(properties, "type")); + for (size_t i = 0; i < std::min(MAX_RIDE_TYPES_PER_RIDE_ENTRY, rideTypes.size()); i++) + { + _legacyType.ride_type[i] = ParseRideType(rideTypes[i]); + } + + auto rideCategories = ObjectJsonHelpers::GetJsonStringArray(json_object_get(properties, "category")); + for (size_t i = 0; i < std::min(MAX_CATEGORIES_PER_RIDE, rideCategories.size()); i++) + { + _legacyType.category[0] = ParseRideCategory(rideCategories[i]); + } + + _legacyType.max_height = ObjectJsonHelpers::GetInteger(properties, "maxHeight"); + + if (IsRideTypeShopOrFacility(_legacyType.ride_type[0])) + { + // Standard car info for a shop + auto &car = _legacyType.vehicles[0]; + car.spacing = 544; + car.sprite_flags = VEHICLE_SPRITE_FLAG_FLAT; + car.sprite_width = 1; + car.sprite_height_negative = 1; + car.sprite_height_positive = 1; + car.flags = VEHICLE_ENTRY_FLAG_SPINNING; + car.car_visual = VEHICLE_VISUAL_FLAT_RIDE_OR_CAR_RIDE; + car.friction_sound_id = 0xFF; + car.sound_range = 0xFF; + car.draw_order = 6; + + // Shop item + auto rideSells = ObjectJsonHelpers::GetJsonStringArray(json_object_get(json_object_get(root, "properties"), "sells")); + _legacyType.shop_item = SHOP_ITEM_NONE; + _legacyType.shop_item_secondary = SHOP_ITEM_NONE; + if (rideSells.size() >= 1) + { + _legacyType.shop_item = ParseShopItem(rideSells[0]); + } + if (rideSells.size() >= 2) + { + _legacyType.shop_item_secondary = ParseShopItem(rideSells[1]); + } + } + else + { + ReadJsonVehicleInfo(context, properties); + + auto ratingMultiplier = json_object_get(properties, "ratingMultipler"); + if (ratingMultiplier != nullptr) + { + _legacyType.excitement_multiplier = ObjectJsonHelpers::GetInteger(ratingMultiplier, "excitement"); + _legacyType.intensity_multiplier = ObjectJsonHelpers::GetInteger(ratingMultiplier, "intensity"); + _legacyType.nausea_multiplier = ObjectJsonHelpers::GetInteger(ratingMultiplier, "nausea"); + } + + auto availableTrackPieces = ObjectJsonHelpers::GetJsonStringArray(json_object_get(properties, "availableTrackPieces")); + } + + _legacyType.flags |= ObjectJsonHelpers::GetFlags(properties, { + { "noInversions", RIDE_ENTRY_FLAG_NO_INVERSIONS }, + { "noBanking", RIDE_ENTRY_FLAG_NO_BANKED_TRACK }, + { "playDepartSound", RIDE_ENTRY_FLAG_PLAY_DEPART_SOUND }, + { "", RIDE_ENTRY_FLAG_ALTERNATIVE_SWING_MODE_1 }, + { "", RIDE_ENTRY_FLAG_ALTERNATIVE_ROTATION_MODE_1 }, + { "", RIDE_ENTRY_FLAG_ALTERNATIVE_ROTATION_MODE_2 }, + { "", RIDE_ENTRY_FLAG_7 }, + { "playSplashSound", RIDE_ENTRY_FLAG_PLAY_SPLASH_SOUND }, + { "playSplashSoundSlide", RIDE_ENTRY_FLAG_PLAY_SPLASH_SOUND_SLIDE }, + { "hasShelter", RIDE_ENTRY_FLAG_COVERED_RIDE }, + { "limitAirTimeBonus", RIDE_ENTRY_FLAG_LIMIT_AIRTIME_BONUS }, + { "separateRide", RIDE_ENTRY_FLAG_SEPARATE_RIDE }, + { "disableBreakdown", RIDE_ENTRY_FLAG_CANNOT_BREAK_DOWN }, + { "", RIDE_ENTRY_FLAG_16 }, + { "", RIDE_ENTRY_FLAG_18 }, + { "disablePainting", RIDE_ENTRY_FLAG_DISABLE_COLOUR_TAB }, + { "", RIDE_ENTRY_FLAG_ALTERNATIVE_SWING_MODE_2 } }); + + ObjectJsonHelpers::LoadStrings(root, GetStringTable()); + ObjectJsonHelpers::LoadImages(root, GetImageTable()); +} + +void RideObject::ReadJsonVehicleInfo(IReadObjectContext * context, const json_t * properties) +{ + _legacyType.min_cars_in_train = json_integer_value(json_object_get(properties, "minCarsPerTrain")); + _legacyType.max_cars_in_train = json_integer_value(json_object_get(properties, "maxCarsPerTrain")); + _legacyType.cars_per_flat_ride = json_integer_value(json_object_get(properties, "carsPerFlatRide")); + _legacyType.zero_cars = json_integer_value(json_object_get(properties, "numEmptyCars")); + + // Train formation from car indices + _legacyType.default_vehicle = json_integer_value(json_object_get(properties, "defaultCar")); + _legacyType.tab_vehicle = json_integer_value(json_object_get(properties, "tabCar")); + auto tabScale = ObjectJsonHelpers::GetFloat(properties, "tabScale"); + if (tabScale != 0 && ObjectJsonHelpers::GetFloat(properties, "tabScale") <= 0.5f) + { + _legacyType.flags |= RIDE_ENTRY_FLAG_VEHICLE_TAB_SCALE_HALF; + } + + auto headCars = ObjectJsonHelpers::GetJsonIntegerArray(json_object_get(properties, "headCars")); + if (headCars.size() >= 1) + { + _legacyType.front_vehicle = headCars[0]; + } + if (headCars.size() >= 2) + { + _legacyType.second_vehicle = headCars[1]; + } + if (headCars.size() >= 3) + { + _legacyType.third_vehicle = headCars[2]; + } + if (headCars.size() >= 4) + { + // More than 3 head cars not supported yet! + } + + auto tailCars = ObjectJsonHelpers::GetJsonIntegerArray(json_object_get(properties, "tailCars")); + if (tailCars.size() >= 1) + { + _legacyType.rear_vehicle = tailCars[0]; + } + if (tailCars.size() >= 2) + { + // More than 1 tail car not supported yet! + } + + ReadJsonCars(json_object_get(properties, "cars")); +} + +std::vector RideObject::ReadJsonCars(const json_t * jCars) +{ + std::vector cars; + json_t * jCar; + size_t index; + json_array_foreach(jCars, index, jCar) + { + auto car = ReadJsonCar(jCar); + cars.push_back(car); + } + return cars; +} + +rct_ride_entry_vehicle RideObject::ReadJsonCar(const json_t * jCar) +{ + rct_ride_entry_vehicle car = { 0 }; + car.rotation_frame_mask = ObjectJsonHelpers::GetInteger(jCar, "rotationFrameMask"); + car.spacing = ObjectJsonHelpers::GetInteger(jCar, "spacing"); + car.car_friction = ObjectJsonHelpers::GetInteger(jCar, "friction"); + car.num_seats = ObjectJsonHelpers::GetInteger(jCar, "numSeats"); + car.no_seating_rows = ObjectJsonHelpers::GetInteger(jCar, "numSeatRows"); + car.powered_acceleration = ObjectJsonHelpers::GetInteger(jCar, "poweredAcceleration"); + car.powered_max_speed = ObjectJsonHelpers::GetInteger(jCar, "poweredMaxSpeed"); + car.effect_visual = ObjectJsonHelpers::GetInteger(jCar, "effectVisual"); + car.draw_order = ObjectJsonHelpers::GetInteger(jCar, "drawOrder"); + return car; +} + +bool RideObject::IsRideTypeShopOrFacility(uint8 rideType) +{ + switch (rideType) + { + case RIDE_TYPE_TOILETS: + case RIDE_TYPE_SHOP: + case RIDE_TYPE_DRINK_STALL: + case RIDE_TYPE_FOOD_STALL: + case RIDE_TYPE_INFORMATION_KIOSK: + case RIDE_TYPE_CASH_MACHINE: + case RIDE_TYPE_FIRST_AID: + return true; + default: + return false; + } +} + +uint8 RideObject::ParseRideType(const std::string &s) { static const std::unordered_map LookupTable { @@ -634,7 +812,7 @@ static uint8 ParseRideType(const std::string &s) RIDE_TYPE_NULL; } -static uint8 ParseRideCategory(const std::string &s) +uint8 RideObject::ParseRideCategory(const std::string &s) { static const std::unordered_map LookupTable { @@ -651,7 +829,7 @@ static uint8 ParseRideCategory(const std::string &s) RIDE_CATEGORY_TRANSPORT; } -static uint8 ParseShopItem(const std::string &s) +uint8 RideObject::ParseShopItem(const std::string &s) { static const std::unordered_map LookupTable { @@ -698,38 +876,3 @@ static uint8 ParseShopItem(const std::string &s) result->second : SHOP_ITEM_NONE; } - -void RideObject::ReadJson(IReadObjectContext * context, const json_t * root) -{ - auto rideTypes = ObjectJsonHelpers::GetJsonStringArray(json_object_get(json_object_get(root, "properties"), "type")); - for (size_t i = 0; i < std::min(MAX_RIDE_TYPES_PER_RIDE_ENTRY, rideTypes.size()); i++) - { - _legacyType.ride_type[i] = ParseRideType(rideTypes[i]); - } - - auto rideCategories = ObjectJsonHelpers::GetJsonStringArray(json_object_get(json_object_get(root, "properties"), "category")); - for (size_t i = 0; i < std::min(MAX_CATEGORIES_PER_RIDE, rideCategories.size()); i++) - { - _legacyType.category[0] = ParseRideCategory(rideCategories[i]); - } - - // Shop item - auto rideSells = ObjectJsonHelpers::GetJsonStringArray(json_object_get(json_object_get(root, "properties"), "sells")); - _legacyType.shop_item = SHOP_ITEM_NONE; - _legacyType.shop_item_secondary = SHOP_ITEM_NONE; - if (rideSells.size() >= 1) - { - _legacyType.shop_item = ParseShopItem(rideSells[0]); - } - if (rideSells.size() >= 2) - { - _legacyType.shop_item_secondary = ParseShopItem(rideSells[1]); - } - - rct_ride_entry_vehicle * vehicle0 = &_legacyType.vehicles[0]; - vehicle0->sprite_flags |= VEHICLE_SPRITE_FLAG_FLAT; - vehicle0->base_image_id = 0; - - ObjectJsonHelpers::LoadStrings(root, GetStringTable()); - ObjectJsonHelpers::LoadImages(root, GetImageTable()); -} diff --git a/src/openrct2/object/RideObject.h b/src/openrct2/object/RideObject.h index b84f586838..3696045742 100644 --- a/src/openrct2/object/RideObject.h +++ b/src/openrct2/object/RideObject.h @@ -16,9 +16,9 @@ #pragma once -#include "Object.h" - +#include #include "../ride/Ride.h" +#include "Object.h" class RideObject final : public Object { @@ -50,6 +50,15 @@ private: void ReadLegacyVehicle(IReadObjectContext * context, IStream * stream, rct_ride_entry_vehicle * vehicle); void PerformFixes(); + void ReadJsonVehicleInfo(IReadObjectContext * context, const json_t * properties); + std::vector ReadJsonCars(const json_t * jCars); + rct_ride_entry_vehicle ReadJsonCar(const json_t * jCar); + static uint8 CalculateNumVerticalFrames(const rct_ride_entry_vehicle * vehicleEntry); static uint8 CalculateNumHorizontalFrames(const rct_ride_entry_vehicle * vehicleEntry); + + static bool IsRideTypeShopOrFacility(uint8 rideType); + static uint8 ParseRideType(const std::string &s); + static uint8 ParseRideCategory(const std::string &s); + static uint8 ParseShopItem(const std::string &s); }; From 7190894ec6b6e50eb1ba22db3634bcffa52e8a57 Mon Sep 17 00:00:00 2001 From: Ted John Date: Wed, 20 Dec 2017 21:47:57 +0000 Subject: [PATCH 41/93] Read JSON colour presets for rides --- src/openrct2/object/RideObject.cpp | 130 +++++++++++++++++++++++++++-- src/openrct2/object/RideObject.h | 3 + 2 files changed, 128 insertions(+), 5 deletions(-) diff --git a/src/openrct2/object/RideObject.cpp b/src/openrct2/object/RideObject.cpp index 385ea40e24..eedddfa164 100644 --- a/src/openrct2/object/RideObject.cpp +++ b/src/openrct2/object/RideObject.cpp @@ -21,10 +21,7 @@ #include "../core/IStream.hpp" #include "../core/Memory.hpp" #include "../core/String.hpp" -#include "../OpenRCT2.h" -#include "ObjectRepository.h" -#include "RideObject.h" - +#include "../core/Util.hpp" #include "../ride/RideGroupManager.h" #include "../drawing/Drawing.h" #include "../localisation/Language.h" @@ -602,6 +599,7 @@ void RideObject::ReadJson(IReadObjectContext * context, const json_t * root) } auto availableTrackPieces = ObjectJsonHelpers::GetJsonStringArray(json_object_get(properties, "availableTrackPieces")); + _presetColours = ReadJsonCarColours(json_object_get(properties, "carColours")); } _legacyType.flags |= ObjectJsonHelpers::GetFlags(properties, { @@ -671,7 +669,12 @@ void RideObject::ReadJsonVehicleInfo(IReadObjectContext * context, const json_t // More than 1 tail car not supported yet! } - ReadJsonCars(json_object_get(properties, "cars")); + auto cars = ReadJsonCars(json_object_get(properties, "cars")); + auto numCars = std::min(Util::CountOf(_legacyType.vehicles), cars.size()); + for (size_t i = 0; i < numCars; i++) + { + _legacyType.vehicles[i] = cars[i]; + } } std::vector RideObject::ReadJsonCars(const json_t * jCars) @@ -693,15 +696,89 @@ rct_ride_entry_vehicle RideObject::ReadJsonCar(const json_t * jCar) car.rotation_frame_mask = ObjectJsonHelpers::GetInteger(jCar, "rotationFrameMask"); car.spacing = ObjectJsonHelpers::GetInteger(jCar, "spacing"); car.car_friction = ObjectJsonHelpers::GetInteger(jCar, "friction"); + car.tab_height = ObjectJsonHelpers::GetInteger(jCar, "tabOffset"); car.num_seats = ObjectJsonHelpers::GetInteger(jCar, "numSeats"); car.no_seating_rows = ObjectJsonHelpers::GetInteger(jCar, "numSeatRows"); + car.spinning_inertia = ObjectJsonHelpers::GetInteger(jCar, "spinningInertia"); + car.spinning_friction = ObjectJsonHelpers::GetInteger(jCar, "spinningFriction"); car.powered_acceleration = ObjectJsonHelpers::GetInteger(jCar, "poweredAcceleration"); car.powered_max_speed = ObjectJsonHelpers::GetInteger(jCar, "poweredMaxSpeed"); + car.car_visual = ObjectJsonHelpers::GetInteger(jCar, "carVisual"); car.effect_visual = ObjectJsonHelpers::GetInteger(jCar, "effectVisual"); car.draw_order = ObjectJsonHelpers::GetInteger(jCar, "drawOrder"); return car; } +vehicle_colour_preset_list RideObject::ReadJsonCarColours(const json_t * jCarColours) +{ + // The JSON supports multiple configurations of per car colours, but + // the ride entry structure currently doesn't allow for it. Assume that + // a single configuration with multiple colour entries is per car scheme. + if (json_array_size(jCarColours) == 1) + { + auto firstElement = json_array_get(jCarColours, 0); + auto numColours = json_array_size(firstElement); + if (numColours >= 2) + { + // Read all colours from first config + auto config = ReadJsonColourConfiguration(firstElement); + vehicle_colour_preset_list list = { 0 }; + list.count = 255; + std::copy_n(config.data(), std::min(numColours, 32), list.list); + return list; + } + } + + // Read first colour for each config + vehicle_colour_preset_list list = { 0 }; + size_t index; + const json_t * jConfiguration; + json_array_foreach(jCarColours, index, jConfiguration) + { + auto config = ReadJsonColourConfiguration(jConfiguration); + if (config.size() >= 1) + { + list.list[index] = config[0]; + list.count++; + + if (list.count == 254) + { + // Reached maximum number of configurations + break; + } + } + } + return list; +} + +std::vector RideObject::ReadJsonColourConfiguration(const json_t * jColourConfig) +{ + std::vector config; + size_t index; + const json_t * jColours; + json_array_foreach(jColourConfig, index, jColours) + { + vehicle_colour carColour = { 0 }; + auto colours = ObjectJsonHelpers::GetJsonStringArray(jColours); + if (colours.size() >= 1) + { + carColour.main = ParseColour(colours[0]); + carColour.additional_1 = carColour.main; + carColour.additional_2 = carColour.main; + if (colours.size() >= 2) + { + carColour.additional_1 = ParseColour(colours[1]); + } + if (colours.size() >= 3) + { + carColour.additional_2 = ParseColour(colours[2]); + } + } + config.push_back(carColour); + } + return config; +} + bool RideObject::IsRideTypeShopOrFacility(uint8 rideType) { switch (rideType) @@ -876,3 +953,46 @@ uint8 RideObject::ParseShopItem(const std::string &s) result->second : SHOP_ITEM_NONE; } + +colour_t RideObject::ParseColour(const std::string &s) +{ + static const std::unordered_map LookupTable + { + { "black", COLOUR_BLACK }, + { "grey", COLOUR_GREY }, + { "white", COLOUR_WHITE }, + { "dark_purple", COLOUR_DARK_PURPLE }, + { "light_purple", COLOUR_LIGHT_PURPLE }, + { "bright_purple", COLOUR_BRIGHT_PURPLE }, + { "dark_blue", COLOUR_DARK_BLUE }, + { "light_blue", COLOUR_LIGHT_BLUE }, + { "icy_blue", COLOUR_ICY_BLUE }, + { "teal", COLOUR_TEAL }, + { "aquamarine", COLOUR_AQUAMARINE }, + { "saturated_green", COLOUR_SATURATED_GREEN }, + { "dark_green", COLOUR_DARK_GREEN }, + { "moss_green", COLOUR_MOSS_GREEN }, + { "bright_green", COLOUR_BRIGHT_GREEN }, + { "olive_green", COLOUR_OLIVE_GREEN }, + { "dark_olive_green", COLOUR_DARK_OLIVE_GREEN }, + { "bright_yellow", COLOUR_BRIGHT_YELLOW }, + { "yellow", COLOUR_YELLOW }, + { "dark_yellow", COLOUR_DARK_YELLOW }, + { "light_orange", COLOUR_LIGHT_ORANGE }, + { "dark_orange", COLOUR_DARK_ORANGE }, + { "light_brown", COLOUR_LIGHT_BROWN }, + { "saturated_brown", COLOUR_SATURATED_BROWN }, + { "dark_brown", COLOUR_DARK_BROWN }, + { "salmon_pink", COLOUR_SALMON_PINK }, + { "bordeaux_red", COLOUR_BORDEAUX_RED }, + { "saturated_red", COLOUR_SATURATED_RED }, + { "bright_red", COLOUR_BRIGHT_RED }, + { "dark_pink", COLOUR_DARK_PINK }, + { "bright_pink", COLOUR_BRIGHT_PINK }, + { "light_pink", COLOUR_LIGHT_PINK }, + }; + auto result = LookupTable.find(s); + return (result != LookupTable.end()) ? + result->second : + COLOUR_BLACK; +} diff --git a/src/openrct2/object/RideObject.h b/src/openrct2/object/RideObject.h index 3696045742..fb920f1d54 100644 --- a/src/openrct2/object/RideObject.h +++ b/src/openrct2/object/RideObject.h @@ -53,6 +53,8 @@ private: void ReadJsonVehicleInfo(IReadObjectContext * context, const json_t * properties); std::vector ReadJsonCars(const json_t * jCars); rct_ride_entry_vehicle ReadJsonCar(const json_t * jCar); + vehicle_colour_preset_list ReadJsonCarColours(const json_t * jCarColours); + std::vector ReadJsonColourConfiguration(const json_t * jColourConfig); static uint8 CalculateNumVerticalFrames(const rct_ride_entry_vehicle * vehicleEntry); static uint8 CalculateNumHorizontalFrames(const rct_ride_entry_vehicle * vehicleEntry); @@ -61,4 +63,5 @@ private: static uint8 ParseRideType(const std::string &s); static uint8 ParseRideCategory(const std::string &s); static uint8 ParseShopItem(const std::string &s); + static colour_t ParseColour(const std::string &s); }; From aec6da1420f5841c8309e708f4d31d4613ec9388 Mon Sep 17 00:00:00 2001 From: Ted John Date: Thu, 21 Dec 2017 00:39:26 +0000 Subject: [PATCH 42/93] Load loading positions from JSON and convert to vector --- src/openrct2/object/RideObject.cpp | 51 +++++++++++++++++++++++------- src/openrct2/object/RideObject.h | 4 +-- 2 files changed, 40 insertions(+), 15 deletions(-) diff --git a/src/openrct2/object/RideObject.cpp b/src/openrct2/object/RideObject.cpp index eedddfa164..0fb3c14f9d 100644 --- a/src/openrct2/object/RideObject.cpp +++ b/src/openrct2/object/RideObject.cpp @@ -19,6 +19,7 @@ #include #include #include "../core/IStream.hpp" +#include "../core/Math.hpp" #include "../core/Memory.hpp" #include "../core/String.hpp" #include "../core/Util.hpp" @@ -35,14 +36,6 @@ using namespace OpenRCT2; -RideObject::~RideObject() -{ - for (auto &peepLoadingPosition : _peepLoadingPositions) - { - Memory::Free(peepLoadingPosition); - } -} - void RideObject::ReadLegacy(IReadObjectContext * context, IStream * stream) { stream->Seek(8, STREAM_SEEK_CURRENT); @@ -105,8 +98,10 @@ void RideObject::ReadLegacy(IReadObjectContext * context, IStream * stream) { numPeepLoadingPositions = stream->ReadValue(); } - _peepLoadingPositions[i] = stream->ReadArray(numPeepLoadingPositions); - _peepLoadingPositionsCount[i] = numPeepLoadingPositions; + + auto data = stream->ReadArray(numPeepLoadingPositions); + _peepLoadingPositions[i] = std::vector(data, data + numPeepLoadingPositions); + Memory::Free(data); } GetImageTable().Read(context, stream); @@ -288,8 +283,8 @@ void RideObject::Load() set_vehicle_type_image_max_sizes(vehicleEntry, num_images); } } - vehicleEntry->peep_loading_positions = _peepLoadingPositions[i]; - vehicleEntry->peep_loading_positions_count = _peepLoadingPositionsCount[i]; + vehicleEntry->peep_loading_positions = _peepLoadingPositions[i].data(); + vehicleEntry->peep_loading_positions_count = (uint16)_peepLoadingPositions[i].size(); } } } @@ -600,6 +595,38 @@ void RideObject::ReadJson(IReadObjectContext * context, const json_t * root) auto availableTrackPieces = ObjectJsonHelpers::GetJsonStringArray(json_object_get(properties, "availableTrackPieces")); _presetColours = ReadJsonCarColours(json_object_get(properties, "carColours")); + + + // Get loading positions + auto loadingPositions = json_object_get(properties, "loadingPositions"); + auto numLoadingPositions = std::min(json_array_size(loadingPositions), 4); + for (size_t i = 0; i < numLoadingPositions; i++) + { + auto positions = json_array_get(loadingPositions, i); + auto numPositions = json_array_size(positions); + if (numPositions > 0 && numPositions <= std::numeric_limits::max()) + { + std::vector positionData; + if (numPositions < 255) + { + positionData.push_back(static_cast(numPositions)); + } + else + { + positionData.push_back(-1); + positionData.push_back(static_cast(numPositions & 0xFF)); + positionData.push_back(static_cast(numPositions >> 8)); + } + + for (size_t j = 0; j < numPositions; j++) + { + auto pos = json_integer_value(json_array_get(positions, j)); + pos = Math::Clamp(std::numeric_limits::min(), pos, std::numeric_limits::max()); + positionData.push_back(pos); + } + _peepLoadingPositions[i] = std::move(positionData); + } + } } _legacyType.flags |= ObjectJsonHelpers::GetFlags(properties, { diff --git a/src/openrct2/object/RideObject.h b/src/openrct2/object/RideObject.h index fb920f1d54..cc4b83088d 100644 --- a/src/openrct2/object/RideObject.h +++ b/src/openrct2/object/RideObject.h @@ -25,12 +25,10 @@ class RideObject final : public Object private: rct_ride_entry _legacyType = { }; vehicle_colour_preset_list _presetColours = { 0 }; - sint8 * _peepLoadingPositions[4] = { nullptr }; - uint16 _peepLoadingPositionsCount[4] = { 0 }; + std::vector _peepLoadingPositions[4]; public: explicit RideObject(const rct_object_entry &entry) : Object(entry) { } - ~RideObject(); void * GetLegacyData() override { return &_legacyType; } From 43c3eca18564c718cdec843ee79cf47ab577747a Mon Sep 17 00:00:00 2001 From: Ted John Date: Fri, 22 Dec 2017 22:58:02 +0000 Subject: [PATCH 43/93] Add remaining flags --- src/openrct2/object/RideObject.cpp | 33 ++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/src/openrct2/object/RideObject.cpp b/src/openrct2/object/RideObject.cpp index 0fb3c14f9d..9dff43d72d 100644 --- a/src/openrct2/object/RideObject.cpp +++ b/src/openrct2/object/RideObject.cpp @@ -585,6 +585,27 @@ void RideObject::ReadJson(IReadObjectContext * context, const json_t * root) { ReadJsonVehicleInfo(context, properties); + auto swingMode = ObjectJsonHelpers::GetInteger(properties, "swingMode"); + if (swingMode == 1) + { + _legacyType.flags |= RIDE_ENTRY_FLAG_ALTERNATIVE_SWING_MODE_1; + } + else if (swingMode == 2) + { + _legacyType.flags |= RIDE_ENTRY_FLAG_ALTERNATIVE_SWING_MODE_1; + _legacyType.flags |= RIDE_ENTRY_FLAG_ALTERNATIVE_SWING_MODE_2; + } + + auto rotationMode = ObjectJsonHelpers::GetInteger(properties, "rotationMode"); + if (rotationMode == 1) + { + _legacyType.flags |= RIDE_ENTRY_FLAG_ALTERNATIVE_ROTATION_MODE_1; + } + else if (rotationMode == 2) + { + _legacyType.flags |= RIDE_ENTRY_FLAG_ALTERNATIVE_ROTATION_MODE_2; + } + auto ratingMultiplier = json_object_get(properties, "ratingMultipler"); if (ratingMultiplier != nullptr) { @@ -633,20 +654,16 @@ void RideObject::ReadJson(IReadObjectContext * context, const json_t * root) { "noInversions", RIDE_ENTRY_FLAG_NO_INVERSIONS }, { "noBanking", RIDE_ENTRY_FLAG_NO_BANKED_TRACK }, { "playDepartSound", RIDE_ENTRY_FLAG_PLAY_DEPART_SOUND }, - { "", RIDE_ENTRY_FLAG_ALTERNATIVE_SWING_MODE_1 }, - { "", RIDE_ENTRY_FLAG_ALTERNATIVE_ROTATION_MODE_1 }, - { "", RIDE_ENTRY_FLAG_ALTERNATIVE_ROTATION_MODE_2 }, - { "", RIDE_ENTRY_FLAG_7 }, + { "RIDE_ENTRY_FLAG_7", RIDE_ENTRY_FLAG_7 }, { "playSplashSound", RIDE_ENTRY_FLAG_PLAY_SPLASH_SOUND }, { "playSplashSoundSlide", RIDE_ENTRY_FLAG_PLAY_SPLASH_SOUND_SLIDE }, { "hasShelter", RIDE_ENTRY_FLAG_COVERED_RIDE }, { "limitAirTimeBonus", RIDE_ENTRY_FLAG_LIMIT_AIRTIME_BONUS }, { "separateRide", RIDE_ENTRY_FLAG_SEPARATE_RIDE }, { "disableBreakdown", RIDE_ENTRY_FLAG_CANNOT_BREAK_DOWN }, - { "", RIDE_ENTRY_FLAG_16 }, - { "", RIDE_ENTRY_FLAG_18 }, - { "disablePainting", RIDE_ENTRY_FLAG_DISABLE_COLOUR_TAB }, - { "", RIDE_ENTRY_FLAG_ALTERNATIVE_SWING_MODE_2 } }); + { "RIDE_ENTRY_FLAG_16", RIDE_ENTRY_FLAG_16 }, + { "RIDE_ENTRY_FLAG_18", RIDE_ENTRY_FLAG_18 }, + { "disablePainting", RIDE_ENTRY_FLAG_DISABLE_COLOUR_TAB } }); ObjectJsonHelpers::LoadStrings(root, GetStringTable()); ObjectJsonHelpers::LoadImages(root, GetImageTable()); From a695dc953e477d3c5c1f18511b32c957df55a5c1 Mon Sep 17 00:00:00 2001 From: Ted John Date: Sat, 23 Dec 2017 19:49:59 +0000 Subject: [PATCH 44/93] Fix import of JSON cars --- src/openrct2/object/RideObject.cpp | 34 ++++++++++++++---------------- 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/src/openrct2/object/RideObject.cpp b/src/openrct2/object/RideObject.cpp index 9dff43d72d..1f12e65b28 100644 --- a/src/openrct2/object/RideObject.cpp +++ b/src/openrct2/object/RideObject.cpp @@ -373,8 +373,7 @@ void RideObject::SetRepositoryItem(ObjectRepositoryItem * item) const void RideObject::ReadLegacyVehicle(IReadObjectContext * context, IStream * stream, rct_ride_entry_vehicle * vehicle) { vehicle->rotation_frame_mask = stream->ReadValue(); - vehicle->num_vertical_frames = stream->ReadValue(); - vehicle->num_horizontal_frames = stream->ReadValue(); + stream->Seek(2 * 1, STREAM_SEEK_CURRENT); vehicle->spacing = stream->ReadValue(); vehicle->car_mass = stream->ReadValue(); vehicle->tab_height = stream->ReadValue(); @@ -386,21 +385,7 @@ void RideObject::ReadLegacyVehicle(IReadObjectContext * context, IStream * strea vehicle->animation = stream->ReadValue(); vehicle->flags = stream->ReadValue(); vehicle->base_num_frames = stream->ReadValue(); - stream->Seek(4, STREAM_SEEK_CURRENT); - vehicle->restraint_image_id = stream->ReadValue(); - vehicle->gentle_slope_image_id = stream->ReadValue(); - vehicle->steep_slope_image_id = stream->ReadValue(); - vehicle->vertical_slope_image_id = stream->ReadValue(); - vehicle->diagonal_slope_image_id = stream->ReadValue(); - vehicle->banked_image_id = stream->ReadValue(); - vehicle->inline_twist_image_id = stream->ReadValue(); - vehicle->flat_to_gentle_bank_image_id = stream->ReadValue(); - vehicle->diagonal_to_gentle_slope_bank_image_id = stream->ReadValue(); - vehicle->gentle_slope_to_bank_image_id = stream->ReadValue(); - vehicle->gentle_slope_bank_turn_image_id = stream->ReadValue(); - vehicle->flat_bank_to_gentle_slope_image_id = stream->ReadValue(); - vehicle->corkscrew_image_id = stream->ReadValue(); - vehicle->no_vehicle_images = stream->ReadValue(); + stream->Seek(15 * 4, STREAM_SEEK_CURRENT); vehicle->no_seating_rows = stream->ReadValue(); vehicle->spinning_inertia = stream->ReadValue(); vehicle->spinning_friction = stream->ReadValue(); @@ -742,14 +727,27 @@ rct_ride_entry_vehicle RideObject::ReadJsonCar(const json_t * jCar) car.car_friction = ObjectJsonHelpers::GetInteger(jCar, "friction"); car.tab_height = ObjectJsonHelpers::GetInteger(jCar, "tabOffset"); car.num_seats = ObjectJsonHelpers::GetInteger(jCar, "numSeats"); + car.sprite_flags = ObjectJsonHelpers::GetInteger(jCar, "spriteFlags"); + car.sprite_width = ObjectJsonHelpers::GetInteger(jCar, "spriteWidth"); + car.sprite_height_negative = ObjectJsonHelpers::GetInteger(jCar, "spriteHeightNegative"); + car.sprite_height_positive = ObjectJsonHelpers::GetInteger(jCar, "spriteHeightPositive"); + car.var_11 = ObjectJsonHelpers::GetInteger(jCar, "var11"); + car.flags = ObjectJsonHelpers::GetInteger(jCar, "flags"); + car.base_num_frames = ObjectJsonHelpers::GetInteger(jCar, "baseNumFrames"); + car.no_vehicle_images = ObjectJsonHelpers::GetInteger(jCar, "numImages"); car.no_seating_rows = ObjectJsonHelpers::GetInteger(jCar, "numSeatRows"); car.spinning_inertia = ObjectJsonHelpers::GetInteger(jCar, "spinningInertia"); car.spinning_friction = ObjectJsonHelpers::GetInteger(jCar, "spinningFriction"); + car.friction_sound_id = ObjectJsonHelpers::GetInteger(jCar, "frictionSoundId", 255); + car.var_58 = ObjectJsonHelpers::GetInteger(jCar, "var58"); + car.sound_range = ObjectJsonHelpers::GetInteger(jCar, "soundRange", 255); + car.var_5A = ObjectJsonHelpers::GetInteger(jCar, "var5A"); car.powered_acceleration = ObjectJsonHelpers::GetInteger(jCar, "poweredAcceleration"); car.powered_max_speed = ObjectJsonHelpers::GetInteger(jCar, "poweredMaxSpeed"); car.car_visual = ObjectJsonHelpers::GetInteger(jCar, "carVisual"); - car.effect_visual = ObjectJsonHelpers::GetInteger(jCar, "effectVisual"); + car.effect_visual = ObjectJsonHelpers::GetInteger(jCar, "effectVisual", 1); car.draw_order = ObjectJsonHelpers::GetInteger(jCar, "drawOrder"); + car.num_vertical_frames_override = ObjectJsonHelpers::GetInteger(jCar, "numVerticalFramesOverride"); return car; } From f700c661d8f67e55912d56b67d584920d270e88e Mon Sep 17 00:00:00 2001 From: Ted John Date: Sat, 23 Dec 2017 19:55:52 +0000 Subject: [PATCH 45/93] Allow cars property to be a single object --- src/openrct2/object/RideObject.cpp | 19 +++++++++++++++---- src/openrct2/ride/Ride.h | 1 + 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/openrct2/object/RideObject.cpp b/src/openrct2/object/RideObject.cpp index 1f12e65b28..c6eef5a738 100644 --- a/src/openrct2/object/RideObject.cpp +++ b/src/openrct2/object/RideObject.cpp @@ -125,6 +125,8 @@ void RideObject::ReadLegacy(IReadObjectContext * context, IStream * stream) void RideObject::Load() { + _legacyType.obj = this; + GetStringTable().Sort(); _legacyType.naming.name = language_allocate_object_string(GetName()); _legacyType.naming.description = language_allocate_object_string(GetDescription()); @@ -709,11 +711,20 @@ void RideObject::ReadJsonVehicleInfo(IReadObjectContext * context, const json_t std::vector RideObject::ReadJsonCars(const json_t * jCars) { std::vector cars; - json_t * jCar; - size_t index; - json_array_foreach(jCars, index, jCar) + + if (json_is_array(jCars)) { - auto car = ReadJsonCar(jCar); + json_t * jCar; + size_t index; + json_array_foreach(jCars, index, jCar) + { + auto car = ReadJsonCar(jCar); + cars.push_back(car); + } + } + else if (json_is_object(jCars)) + { + auto car = ReadJsonCar(jCars); cars.push_back(car); } return cars; diff --git a/src/openrct2/ride/Ride.h b/src/openrct2/ride/Ride.h index 67ff350652..a112fd6cf6 100644 --- a/src/openrct2/ride/Ride.h +++ b/src/openrct2/ride/Ride.h @@ -126,6 +126,7 @@ struct rct_ride_entry { uint8 shop_item; // 0x1C0 uint8 shop_item_secondary; // 0x1C1 rct_string_id capacity; + void * obj; }; #pragma pack(pop) From 34168b6ecc0749d987dd0b54257e811ac272b929 Mon Sep 17 00:00:00 2001 From: Ted John Date: Sat, 23 Dec 2017 20:37:44 +0000 Subject: [PATCH 46/93] Import sprite flags as named flags --- src/openrct2/object/RideObject.cpp | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/openrct2/object/RideObject.cpp b/src/openrct2/object/RideObject.cpp index c6eef5a738..e6c60445ed 100644 --- a/src/openrct2/object/RideObject.cpp +++ b/src/openrct2/object/RideObject.cpp @@ -738,7 +738,6 @@ rct_ride_entry_vehicle RideObject::ReadJsonCar(const json_t * jCar) car.car_friction = ObjectJsonHelpers::GetInteger(jCar, "friction"); car.tab_height = ObjectJsonHelpers::GetInteger(jCar, "tabOffset"); car.num_seats = ObjectJsonHelpers::GetInteger(jCar, "numSeats"); - car.sprite_flags = ObjectJsonHelpers::GetInteger(jCar, "spriteFlags"); car.sprite_width = ObjectJsonHelpers::GetInteger(jCar, "spriteWidth"); car.sprite_height_negative = ObjectJsonHelpers::GetInteger(jCar, "spriteHeightNegative"); car.sprite_height_positive = ObjectJsonHelpers::GetInteger(jCar, "spriteHeightPositive"); @@ -759,6 +758,25 @@ rct_ride_entry_vehicle RideObject::ReadJsonCar(const json_t * jCar) car.effect_visual = ObjectJsonHelpers::GetInteger(jCar, "effectVisual", 1); car.draw_order = ObjectJsonHelpers::GetInteger(jCar, "drawOrder"); car.num_vertical_frames_override = ObjectJsonHelpers::GetInteger(jCar, "numVerticalFramesOverride"); + + auto jFrames = json_object_get(jCar, "frames"); + car.sprite_flags = ObjectJsonHelpers::GetFlags(jFrames, { + { "flat", VEHICLE_SPRITE_FLAG_FLAT }, + { "gentleSlopes", VEHICLE_SPRITE_FLAG_GENTLE_SLOPES }, + { "steepSlopes", VEHICLE_SPRITE_FLAG_STEEP_SLOPES }, + { "verticalSlopes", VEHICLE_SPRITE_FLAG_VERTICAL_SLOPES }, + { "diagonalSlopes", VEHICLE_SPRITE_FLAG_DIAGONAL_SLOPES }, + { "flatBanked", VEHICLE_SPRITE_FLAG_FLAT_BANKED }, + { "inlineTwists", VEHICLE_SPRITE_FLAG_INLINE_TWISTS }, + { "flatToGentleSlopeBankedTransitions", VEHICLE_SPRITE_FLAG_FLAT_TO_GENTLE_SLOPE_BANKED_TRANSITIONS }, + { "diagonalGentleSlopeBankedTransitions", VEHICLE_SPRITE_FLAG_DIAGONAL_GENTLE_SLOPE_BANKED_TRANSITIONS }, + { "gentleSlopeBankedTransitions", VEHICLE_SPRITE_FLAG_GENTLE_SLOPE_BANKED_TRANSITIONS }, + { "gentleSlopeBankedTurns", VEHICLE_SPRITE_FLAG_GENTLE_SLOPE_BANKED_TURNS }, + { "flatToGentleSlopeWhileBankedTransitions", VEHICLE_SPRITE_FLAG_FLAT_TO_GENTLE_SLOPE_WHILE_BANKED_TRANSITIONS }, + { "corkscrews", VEHICLE_SPRITE_FLAG_CORKSCREWS }, + { "restraintAnimation", VEHICLE_SPRITE_FLAG_RESTRAINT_ANIMATION }, + { "VEHICLE_SPRITE_FLAG_14", VEHICLE_SPRITE_FLAG_14 }, + { "VEHICLE_SPRITE_FLAG_15", VEHICLE_SPRITE_FLAG_15 } }); return car; } From 2917336e75d5513665c5bf9684fd496c4f32a984 Mon Sep 17 00:00:00 2001 From: Ted John Date: Sat, 23 Dec 2017 23:08:56 +0000 Subject: [PATCH 47/93] Fix import of ride type and category --- src/openrct2/object/RideObject.cpp | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/openrct2/object/RideObject.cpp b/src/openrct2/object/RideObject.cpp index e6c60445ed..17ebab3e05 100644 --- a/src/openrct2/object/RideObject.cpp +++ b/src/openrct2/object/RideObject.cpp @@ -527,15 +527,22 @@ void RideObject::ReadJson(IReadObjectContext * context, const json_t * root) auto properties = json_object_get(root, "properties"); auto rideTypes = ObjectJsonHelpers::GetJsonStringArray(json_object_get(properties, "type")); - for (size_t i = 0; i < std::min(MAX_RIDE_TYPES_PER_RIDE_ENTRY, rideTypes.size()); i++) + for (size_t i = 0; i < MAX_RIDE_TYPES_PER_RIDE_ENTRY; i++) { - _legacyType.ride_type[i] = ParseRideType(rideTypes[i]); + _legacyType.ride_type[i] = (rideTypes.size() > i) ? + ParseRideType(rideTypes[i]) : + RIDE_TYPE_NULL; } auto rideCategories = ObjectJsonHelpers::GetJsonStringArray(json_object_get(properties, "category")); - for (size_t i = 0; i < std::min(MAX_CATEGORIES_PER_RIDE, rideCategories.size()); i++) + if (rideCategories.size() >= 1) { - _legacyType.category[0] = ParseRideCategory(rideCategories[i]); + _legacyType.category[0] = ParseRideCategory(rideCategories[0]); + _legacyType.category[1] = _legacyType.category[0]; + } + if (rideCategories.size() >= 2) + { + _legacyType.category[1] = ParseRideCategory(rideCategories[1]); } _legacyType.max_height = ObjectJsonHelpers::GetInteger(properties, "maxHeight"); From 1d0799fc0d4bd6f0064acdb0bf681c45b71b0434 Mon Sep 17 00:00:00 2001 From: Ted John Date: Sat, 23 Dec 2017 23:09:05 +0000 Subject: [PATCH 48/93] Import named car flags --- src/openrct2/object/RideObject.cpp | 35 +++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/src/openrct2/object/RideObject.cpp b/src/openrct2/object/RideObject.cpp index 17ebab3e05..0eb35ff115 100644 --- a/src/openrct2/object/RideObject.cpp +++ b/src/openrct2/object/RideObject.cpp @@ -749,7 +749,6 @@ rct_ride_entry_vehicle RideObject::ReadJsonCar(const json_t * jCar) car.sprite_height_negative = ObjectJsonHelpers::GetInteger(jCar, "spriteHeightNegative"); car.sprite_height_positive = ObjectJsonHelpers::GetInteger(jCar, "spriteHeightPositive"); car.var_11 = ObjectJsonHelpers::GetInteger(jCar, "var11"); - car.flags = ObjectJsonHelpers::GetInteger(jCar, "flags"); car.base_num_frames = ObjectJsonHelpers::GetInteger(jCar, "baseNumFrames"); car.no_vehicle_images = ObjectJsonHelpers::GetInteger(jCar, "numImages"); car.no_seating_rows = ObjectJsonHelpers::GetInteger(jCar, "numSeatRows"); @@ -784,6 +783,40 @@ rct_ride_entry_vehicle RideObject::ReadJsonCar(const json_t * jCar) { "restraintAnimation", VEHICLE_SPRITE_FLAG_RESTRAINT_ANIMATION }, { "VEHICLE_SPRITE_FLAG_14", VEHICLE_SPRITE_FLAG_14 }, { "VEHICLE_SPRITE_FLAG_15", VEHICLE_SPRITE_FLAG_15 } }); + + car.flags = ObjectJsonHelpers::GetFlags(jCar, { + { "VEHICLE_ENTRY_FLAG_0", VEHICLE_ENTRY_FLAG_0 }, + { "VEHICLE_ENTRY_FLAG_NO_UPSTOP_WHEELS", VEHICLE_ENTRY_FLAG_NO_UPSTOP_WHEELS }, + { "VEHICLE_ENTRY_FLAG_NO_UPSTOP_BOBSLEIGH", VEHICLE_ENTRY_FLAG_NO_UPSTOP_BOBSLEIGH }, + { "VEHICLE_ENTRY_FLAG_MINI_GOLF", VEHICLE_ENTRY_FLAG_MINI_GOLF }, + { "VEHICLE_ENTRY_FLAG_4", VEHICLE_ENTRY_FLAG_4 }, + { "VEHICLE_ENTRY_FLAG_5", VEHICLE_ENTRY_FLAG_5 }, + { "VEHICLE_ENTRY_FLAG_HAS_INVERTED_SPRITE_SET", VEHICLE_ENTRY_FLAG_HAS_INVERTED_SPRITE_SET }, + { "VEHICLE_ENTRY_FLAG_7", VEHICLE_ENTRY_FLAG_7 }, + { "VEHICLE_ENTRY_FLAG_ALLOW_DOORS_DEPRECATED", VEHICLE_ENTRY_FLAG_ALLOW_DOORS_DEPRECATED }, + { "VEHICLE_ENTRY_FLAG_ENABLE_ADDITIONAL_COLOUR_2", VEHICLE_ENTRY_FLAG_ENABLE_ADDITIONAL_COLOUR_2 }, + { "VEHICLE_ENTRY_FLAG_10", VEHICLE_ENTRY_FLAG_10 }, + { "VEHICLE_ENTRY_FLAG_11", VEHICLE_ENTRY_FLAG_11 }, + { "VEHICLE_ENTRY_FLAG_OVERRIDE_NUM_VERTICAL_FRAMES", VEHICLE_ENTRY_FLAG_OVERRIDE_NUM_VERTICAL_FRAMES }, + { "VEHICLE_ENTRY_FLAG_13", VEHICLE_ENTRY_FLAG_13 }, + { "VEHICLE_ENTRY_FLAG_14", VEHICLE_ENTRY_FLAG_14 }, + { "VEHICLE_ENTRY_FLAG_15", VEHICLE_ENTRY_FLAG_15 }, + { "VEHICLE_ENTRY_FLAG_ENABLE_ADDITIONAL_COLOUR_1", VEHICLE_ENTRY_FLAG_ENABLE_ADDITIONAL_COLOUR_1 }, + { "VEHICLE_ENTRY_FLAG_SWINGING", VEHICLE_ENTRY_FLAG_SWINGING }, + { "VEHICLE_ENTRY_FLAG_SPINNING", VEHICLE_ENTRY_FLAG_SPINNING }, + { "VEHICLE_ENTRY_FLAG_POWERED", VEHICLE_ENTRY_FLAG_POWERED }, + { "VEHICLE_ENTRY_FLAG_RIDERS_SCREAM", VEHICLE_ENTRY_FLAG_RIDERS_SCREAM }, + { "VEHICLE_ENTRY_FLAG_21", VEHICLE_ENTRY_FLAG_21 }, + { "VEHICLE_ENTRY_FLAG_22", VEHICLE_ENTRY_FLAG_22 }, + { "VEHICLE_ENTRY_FLAG_23", VEHICLE_ENTRY_FLAG_23 }, + { "VEHICLE_ENTRY_FLAG_24", VEHICLE_ENTRY_FLAG_24 }, + { "VEHICLE_ENTRY_FLAG_25", VEHICLE_ENTRY_FLAG_25 }, + { "VEHICLE_ENTRY_FLAG_26", VEHICLE_ENTRY_FLAG_26 }, + { "VEHICLE_ENTRY_FLAG_27", VEHICLE_ENTRY_FLAG_27 }, + { "VEHICLE_ENTRY_FLAG_28", VEHICLE_ENTRY_FLAG_28 }, + { "VEHICLE_ENTRY_FLAG_29", VEHICLE_ENTRY_FLAG_29 }, + { "VEHICLE_ENTRY_FLAG_30", VEHICLE_ENTRY_FLAG_30 }, + { "VEHICLE_ENTRY_FLAG_31", VEHICLE_ENTRY_FLAG_31 } }); return car; } From 81a2c28e1b68e17d1e98d2f86407ce93e6f71445 Mon Sep 17 00:00:00 2001 From: Gymnasiast Date: Sun, 31 Dec 2017 14:54:17 +0100 Subject: [PATCH 49/93] Small fixes --- src/openrct2/object/RideObject.cpp | 2 +- src/openrct2/object/RideObject.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/openrct2/object/RideObject.cpp b/src/openrct2/object/RideObject.cpp index 0eb35ff115..a2f0c2ebc5 100644 --- a/src/openrct2/object/RideObject.cpp +++ b/src/openrct2/object/RideObject.cpp @@ -742,7 +742,7 @@ rct_ride_entry_vehicle RideObject::ReadJsonCar(const json_t * jCar) rct_ride_entry_vehicle car = { 0 }; car.rotation_frame_mask = ObjectJsonHelpers::GetInteger(jCar, "rotationFrameMask"); car.spacing = ObjectJsonHelpers::GetInteger(jCar, "spacing"); - car.car_friction = ObjectJsonHelpers::GetInteger(jCar, "friction"); + car.car_mass = ObjectJsonHelpers::GetInteger(jCar, "mass"); car.tab_height = ObjectJsonHelpers::GetInteger(jCar, "tabOffset"); car.num_seats = ObjectJsonHelpers::GetInteger(jCar, "numSeats"); car.sprite_width = ObjectJsonHelpers::GetInteger(jCar, "spriteWidth"); diff --git a/src/openrct2/object/RideObject.h b/src/openrct2/object/RideObject.h index cc4b83088d..0e90c6d2ec 100644 --- a/src/openrct2/object/RideObject.h +++ b/src/openrct2/object/RideObject.h @@ -25,7 +25,7 @@ class RideObject final : public Object private: rct_ride_entry _legacyType = { }; vehicle_colour_preset_list _presetColours = { 0 }; - std::vector _peepLoadingPositions[4]; + std::vector _peepLoadingPositions[MAX_VEHICLES_PER_RIDE_ENTRY]; public: explicit RideObject(const rct_object_entry &entry) : Object(entry) { } From b207797ad27d4c06c4d26b98f278904e857618af Mon Sep 17 00:00:00 2001 From: Gymnasiast Date: Mon, 22 Jan 2018 15:36:16 +0100 Subject: [PATCH 50/93] Fix rebase errors --- src/openrct2/object/ObjectFactory.cpp | 4 ++-- src/openrct2/object/ObjectJsonHelpers.cpp | 2 +- src/openrct2/object/ObjectJsonHelpers.h | 4 ++-- src/openrct2/object/RideObject.cpp | 2 +- src/openrct2/sprites.h | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/openrct2/object/ObjectFactory.cpp b/src/openrct2/object/ObjectFactory.cpp index a399fe5b1b..1f18245ffb 100644 --- a/src/openrct2/object/ObjectFactory.cpp +++ b/src/openrct2/object/ObjectFactory.cpp @@ -253,13 +253,13 @@ namespace ObjectFactory result->ReadJson(&readContext, jRoot); if (readContext.WasError()) { - throw Exception("Object has errors"); + throw std::runtime_error("Object has errors"); } } } json_decref(jRoot); } - catch (Exception) + catch (std::runtime_error) { Console::Error::WriteLine("Unable to open or read '%s'", path.c_str()); diff --git a/src/openrct2/object/ObjectJsonHelpers.cpp b/src/openrct2/object/ObjectJsonHelpers.cpp index c3e3a4148e..20325f724e 100644 --- a/src/openrct2/object/ObjectJsonHelpers.cpp +++ b/src/openrct2/object/ObjectJsonHelpers.cpp @@ -23,7 +23,7 @@ #include "../core/Path.hpp" #include "../core/String.hpp" #include "../interface/Cursors.h" -#include "../localisation/language.h" +#include "../localisation/Language.h" #include "../PlatformEnvironment.h" #include "../sprites.h" #include "Object.h" diff --git a/src/openrct2/object/ObjectJsonHelpers.h b/src/openrct2/object/ObjectJsonHelpers.h index ae13934ba0..4a0761db89 100644 --- a/src/openrct2/object/ObjectJsonHelpers.h +++ b/src/openrct2/object/ObjectJsonHelpers.h @@ -22,8 +22,8 @@ #include #include "../common.h" #include "../core/Json.hpp" -#include "../drawing/drawing.h" -#include "../object.h" +#include "../drawing/Drawing.h" +#include "../object/Object.h" #include "ImageTable.h" #include "StringTable.h" diff --git a/src/openrct2/object/RideObject.cpp b/src/openrct2/object/RideObject.cpp index a2f0c2ebc5..27a4abfc88 100644 --- a/src/openrct2/object/RideObject.cpp +++ b/src/openrct2/object/RideObject.cpp @@ -757,7 +757,7 @@ rct_ride_entry_vehicle RideObject::ReadJsonCar(const json_t * jCar) car.friction_sound_id = ObjectJsonHelpers::GetInteger(jCar, "frictionSoundId", 255); car.var_58 = ObjectJsonHelpers::GetInteger(jCar, "var58"); car.sound_range = ObjectJsonHelpers::GetInteger(jCar, "soundRange", 255); - car.var_5A = ObjectJsonHelpers::GetInteger(jCar, "var5A"); + car.double_sound_frequency = ObjectJsonHelpers::GetInteger(jCar, "var5A"); car.powered_acceleration = ObjectJsonHelpers::GetInteger(jCar, "poweredAcceleration"); car.powered_max_speed = ObjectJsonHelpers::GetInteger(jCar, "poweredMaxSpeed"); car.car_visual = ObjectJsonHelpers::GetInteger(jCar, "carVisual"); diff --git a/src/openrct2/sprites.h b/src/openrct2/sprites.h index e0d1001b91..f681a87f4e 100644 --- a/src/openrct2/sprites.h +++ b/src/openrct2/sprites.h @@ -17,7 +17,7 @@ #ifndef _SPRITES_H_ #define _SPRITES_H_ -#include +#include "rct1/RCT1.h" enum { SPR_NONE = -1, From 7ea5c1f09986b4e29a288d96b9df67a27052a8db Mon Sep 17 00:00:00 2001 From: Ted John Date: Wed, 7 Feb 2018 20:37:20 +0000 Subject: [PATCH 51/93] Fix errors --- src/openrct2/object/ObjectJsonHelpers.cpp | 20 ++++++++++------ src/openrct2/object/RideObject.cpp | 28 +++++++++++----------- src/openrct2/object/SceneryGroupObject.cpp | 4 ++-- 3 files changed, 29 insertions(+), 23 deletions(-) diff --git a/src/openrct2/object/ObjectJsonHelpers.cpp b/src/openrct2/object/ObjectJsonHelpers.cpp index 20325f724e..647b52beec 100644 --- a/src/openrct2/object/ObjectJsonHelpers.cpp +++ b/src/openrct2/object/ObjectJsonHelpers.cpp @@ -16,6 +16,8 @@ #pragma warning(disable : 4706) // assignment within conditional expression +#include +#include #include #include "../Context.h" #include "../core/Math.hpp" @@ -217,9 +219,11 @@ namespace ObjectJsonHelpers auto images = imgTable.GetImages(); for (uint32 i = start; i < Math::Min(numImages, end); i++) { - auto g1 = images[i]; - auto length = g1_calculate_data_size(&g1); - g1.offset = Memory::Duplicate(g1.offset, length); + auto &objg1 = images[i]; + auto length = g1_calculate_data_size(&objg1); + auto g1 = objg1; + g1.offset = (uint8 *)std::malloc(length); + std::memcpy(g1.offset, objg1.offset, length); result.push_back(g1); } delete obj; @@ -260,9 +264,11 @@ namespace ObjectJsonHelpers { for (auto i : range) { - auto g1 = *gfx_get_g1_element(SPR_CSG_BEGIN + i); - auto length = g1_calculate_data_size(&g1); - g1.offset = Memory::Duplicate(g1.offset, length); + auto &csg1 = *gfx_get_g1_element(SPR_CSG_BEGIN + i); + auto length = g1_calculate_data_size(&csg1); + auto g1 = csg1; + g1.offset = (uint8 *)std::malloc(length); + std::memcpy(g1.offset, csg1.offset, length); result.push_back(g1); } } @@ -336,7 +342,7 @@ namespace ObjectJsonHelpers for (const auto &g1 : images) { imageTable.AddImage(&g1); - Memory::Free(g1.offset); + std::free(g1.offset); } } } diff --git a/src/openrct2/object/RideObject.cpp b/src/openrct2/object/RideObject.cpp index 27a4abfc88..4afb8717bc 100644 --- a/src/openrct2/object/RideObject.cpp +++ b/src/openrct2/object/RideObject.cpp @@ -748,14 +748,14 @@ rct_ride_entry_vehicle RideObject::ReadJsonCar(const json_t * jCar) car.sprite_width = ObjectJsonHelpers::GetInteger(jCar, "spriteWidth"); car.sprite_height_negative = ObjectJsonHelpers::GetInteger(jCar, "spriteHeightNegative"); car.sprite_height_positive = ObjectJsonHelpers::GetInteger(jCar, "spriteHeightPositive"); - car.var_11 = ObjectJsonHelpers::GetInteger(jCar, "var11"); + car.animation = ObjectJsonHelpers::GetInteger(jCar, "var11"); car.base_num_frames = ObjectJsonHelpers::GetInteger(jCar, "baseNumFrames"); car.no_vehicle_images = ObjectJsonHelpers::GetInteger(jCar, "numImages"); car.no_seating_rows = ObjectJsonHelpers::GetInteger(jCar, "numSeatRows"); car.spinning_inertia = ObjectJsonHelpers::GetInteger(jCar, "spinningInertia"); car.spinning_friction = ObjectJsonHelpers::GetInteger(jCar, "spinningFriction"); car.friction_sound_id = ObjectJsonHelpers::GetInteger(jCar, "frictionSoundId", 255); - car.var_58 = ObjectJsonHelpers::GetInteger(jCar, "var58"); + car.log_flume_reverser_vehicle_type = ObjectJsonHelpers::GetInteger(jCar, "var58"); car.sound_range = ObjectJsonHelpers::GetInteger(jCar, "soundRange", 255); car.double_sound_frequency = ObjectJsonHelpers::GetInteger(jCar, "var5A"); car.powered_acceleration = ObjectJsonHelpers::GetInteger(jCar, "poweredAcceleration"); @@ -781,25 +781,25 @@ rct_ride_entry_vehicle RideObject::ReadJsonCar(const json_t * jCar) { "flatToGentleSlopeWhileBankedTransitions", VEHICLE_SPRITE_FLAG_FLAT_TO_GENTLE_SLOPE_WHILE_BANKED_TRANSITIONS }, { "corkscrews", VEHICLE_SPRITE_FLAG_CORKSCREWS }, { "restraintAnimation", VEHICLE_SPRITE_FLAG_RESTRAINT_ANIMATION }, - { "VEHICLE_SPRITE_FLAG_14", VEHICLE_SPRITE_FLAG_14 }, + { "curvedLiftHill", VEHICLE_SPRITE_FLAG_CURVED_LIFT_HILL }, { "VEHICLE_SPRITE_FLAG_15", VEHICLE_SPRITE_FLAG_15 } }); car.flags = ObjectJsonHelpers::GetFlags(jCar, { - { "VEHICLE_ENTRY_FLAG_0", VEHICLE_ENTRY_FLAG_0 }, + { "VEHICLE_ENTRY_FLAG_POWERED_RIDE_UNRESTRICTED_GRAVITY", VEHICLE_ENTRY_FLAG_POWERED_RIDE_UNRESTRICTED_GRAVITY }, { "VEHICLE_ENTRY_FLAG_NO_UPSTOP_WHEELS", VEHICLE_ENTRY_FLAG_NO_UPSTOP_WHEELS }, { "VEHICLE_ENTRY_FLAG_NO_UPSTOP_BOBSLEIGH", VEHICLE_ENTRY_FLAG_NO_UPSTOP_BOBSLEIGH }, { "VEHICLE_ENTRY_FLAG_MINI_GOLF", VEHICLE_ENTRY_FLAG_MINI_GOLF }, { "VEHICLE_ENTRY_FLAG_4", VEHICLE_ENTRY_FLAG_4 }, { "VEHICLE_ENTRY_FLAG_5", VEHICLE_ENTRY_FLAG_5 }, { "VEHICLE_ENTRY_FLAG_HAS_INVERTED_SPRITE_SET", VEHICLE_ENTRY_FLAG_HAS_INVERTED_SPRITE_SET }, - { "VEHICLE_ENTRY_FLAG_7", VEHICLE_ENTRY_FLAG_7 }, + { "VEHICLE_ENTRY_FLAG_DODGEM_INUSE_LIGHTS", VEHICLE_ENTRY_FLAG_DODGEM_INUSE_LIGHTS }, { "VEHICLE_ENTRY_FLAG_ALLOW_DOORS_DEPRECATED", VEHICLE_ENTRY_FLAG_ALLOW_DOORS_DEPRECATED }, { "VEHICLE_ENTRY_FLAG_ENABLE_ADDITIONAL_COLOUR_2", VEHICLE_ENTRY_FLAG_ENABLE_ADDITIONAL_COLOUR_2 }, { "VEHICLE_ENTRY_FLAG_10", VEHICLE_ENTRY_FLAG_10 }, { "VEHICLE_ENTRY_FLAG_11", VEHICLE_ENTRY_FLAG_11 }, { "VEHICLE_ENTRY_FLAG_OVERRIDE_NUM_VERTICAL_FRAMES", VEHICLE_ENTRY_FLAG_OVERRIDE_NUM_VERTICAL_FRAMES }, { "VEHICLE_ENTRY_FLAG_13", VEHICLE_ENTRY_FLAG_13 }, - { "VEHICLE_ENTRY_FLAG_14", VEHICLE_ENTRY_FLAG_14 }, + { "VEHICLE_ENTRY_FLAG_SPINNING_ADDITIONAL_FRAMES", VEHICLE_ENTRY_FLAG_SPINNING_ADDITIONAL_FRAMES }, { "VEHICLE_ENTRY_FLAG_15", VEHICLE_ENTRY_FLAG_15 }, { "VEHICLE_ENTRY_FLAG_ENABLE_ADDITIONAL_COLOUR_1", VEHICLE_ENTRY_FLAG_ENABLE_ADDITIONAL_COLOUR_1 }, { "VEHICLE_ENTRY_FLAG_SWINGING", VEHICLE_ENTRY_FLAG_SWINGING }, @@ -807,16 +807,16 @@ rct_ride_entry_vehicle RideObject::ReadJsonCar(const json_t * jCar) { "VEHICLE_ENTRY_FLAG_POWERED", VEHICLE_ENTRY_FLAG_POWERED }, { "VEHICLE_ENTRY_FLAG_RIDERS_SCREAM", VEHICLE_ENTRY_FLAG_RIDERS_SCREAM }, { "VEHICLE_ENTRY_FLAG_21", VEHICLE_ENTRY_FLAG_21 }, - { "VEHICLE_ENTRY_FLAG_22", VEHICLE_ENTRY_FLAG_22 }, - { "VEHICLE_ENTRY_FLAG_23", VEHICLE_ENTRY_FLAG_23 }, - { "VEHICLE_ENTRY_FLAG_24", VEHICLE_ENTRY_FLAG_24 }, + { "VEHICLE_ENTRY_FLAG_BOAT_HIRE_COLLISION_DETECTION", VEHICLE_ENTRY_FLAG_BOAT_HIRE_COLLISION_DETECTION }, + { "VEHICLE_ENTRY_FLAG_VEHICLE_ANIMATION", VEHICLE_ENTRY_FLAG_VEHICLE_ANIMATION }, + { "VEHICLE_ENTRY_FLAG_RIDER_ANIMATION", VEHICLE_ENTRY_FLAG_RIDER_ANIMATION }, { "VEHICLE_ENTRY_FLAG_25", VEHICLE_ENTRY_FLAG_25 }, { "VEHICLE_ENTRY_FLAG_26", VEHICLE_ENTRY_FLAG_26 }, - { "VEHICLE_ENTRY_FLAG_27", VEHICLE_ENTRY_FLAG_27 }, - { "VEHICLE_ENTRY_FLAG_28", VEHICLE_ENTRY_FLAG_28 }, - { "VEHICLE_ENTRY_FLAG_29", VEHICLE_ENTRY_FLAG_29 }, - { "VEHICLE_ENTRY_FLAG_30", VEHICLE_ENTRY_FLAG_30 }, - { "VEHICLE_ENTRY_FLAG_31", VEHICLE_ENTRY_FLAG_31 } }); + { "VEHICLE_ENTRY_FLAG_SLIDE_SWING", VEHICLE_ENTRY_FLAG_SLIDE_SWING }, + { "VEHICLE_ENTRY_FLAG_CHAIRLIFT", VEHICLE_ENTRY_FLAG_CHAIRLIFT }, + { "VEHICLE_ENTRY_FLAG_WATER_RIDE", VEHICLE_ENTRY_FLAG_WATER_RIDE }, + { "VEHICLE_ENTRY_FLAG_GO_KART", VEHICLE_ENTRY_FLAG_GO_KART }, + { "VEHICLE_ENTRY_FLAG_DODGEM_CAR_PLACEMENT", VEHICLE_ENTRY_FLAG_DODGEM_CAR_PLACEMENT } }); return car; } diff --git a/src/openrct2/object/SceneryGroupObject.cpp b/src/openrct2/object/SceneryGroupObject.cpp index e43827704f..d6ea8d6902 100644 --- a/src/openrct2/object/SceneryGroupObject.cpp +++ b/src/openrct2/object/SceneryGroupObject.cpp @@ -38,9 +38,9 @@ void SceneryGroupObject::ReadLegacy(IReadObjectContext * context, IStream * stre _legacyType.pad_109 = stream->ReadValue(); _legacyType.entertainer_costumes = stream->ReadValue(); - GetStringTable()->Read(context, stream, OBJ_STRING_ID_NAME); + GetStringTable().Read(context, stream, OBJ_STRING_ID_NAME); _items = ReadItems(stream); - GetImageTable()->Read(context, stream); + GetImageTable().Read(context, stream); } void SceneryGroupObject::Load() From 668f9fd18b58d9040395ec8bf5815d9bfc21ec04 Mon Sep 17 00:00:00 2001 From: Ted John Date: Wed, 7 Feb 2018 21:14:13 +0000 Subject: [PATCH 52/93] Correct some ride JSON names --- src/openrct2/object/ObjectFactory.cpp | 2 +- src/openrct2/object/RideObject.cpp | 24 ++++++++++++++++-------- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/openrct2/object/ObjectFactory.cpp b/src/openrct2/object/ObjectFactory.cpp index 1f18245ffb..1c276f5a04 100644 --- a/src/openrct2/object/ObjectFactory.cpp +++ b/src/openrct2/object/ObjectFactory.cpp @@ -65,7 +65,7 @@ public: if (!String::IsNullOrEmpty(text)) { - log_verbose("[%s] Warning: %s", _objectName, text); + Console::Error::WriteLine("[%s] Warning: %s", _objectName, text); } } diff --git a/src/openrct2/object/RideObject.cpp b/src/openrct2/object/RideObject.cpp index 4afb8717bc..58f30998b0 100644 --- a/src/openrct2/object/RideObject.cpp +++ b/src/openrct2/object/RideObject.cpp @@ -529,9 +529,17 @@ void RideObject::ReadJson(IReadObjectContext * context, const json_t * root) auto rideTypes = ObjectJsonHelpers::GetJsonStringArray(json_object_get(properties, "type")); for (size_t i = 0; i < MAX_RIDE_TYPES_PER_RIDE_ENTRY; i++) { - _legacyType.ride_type[i] = (rideTypes.size() > i) ? - ParseRideType(rideTypes[i]) : - RIDE_TYPE_NULL; + uint8 rideType = RIDE_TYPE_NULL; + if (i < rideTypes.size()) + { + rideType = ParseRideType(rideTypes[i]); + if (rideType == RIDE_TYPE_NULL) + { + context->LogWarning(OBJECT_ERROR_INVALID_PROPERTY, "Unknown ride type"); + } + } + + _legacyType.ride_type[i] = rideType; } auto rideCategories = ObjectJsonHelpers::GetJsonStringArray(json_object_get(properties, "category")); @@ -748,16 +756,16 @@ rct_ride_entry_vehicle RideObject::ReadJsonCar(const json_t * jCar) car.sprite_width = ObjectJsonHelpers::GetInteger(jCar, "spriteWidth"); car.sprite_height_negative = ObjectJsonHelpers::GetInteger(jCar, "spriteHeightNegative"); car.sprite_height_positive = ObjectJsonHelpers::GetInteger(jCar, "spriteHeightPositive"); - car.animation = ObjectJsonHelpers::GetInteger(jCar, "var11"); + car.animation = ObjectJsonHelpers::GetInteger(jCar, "animation"); car.base_num_frames = ObjectJsonHelpers::GetInteger(jCar, "baseNumFrames"); car.no_vehicle_images = ObjectJsonHelpers::GetInteger(jCar, "numImages"); car.no_seating_rows = ObjectJsonHelpers::GetInteger(jCar, "numSeatRows"); car.spinning_inertia = ObjectJsonHelpers::GetInteger(jCar, "spinningInertia"); car.spinning_friction = ObjectJsonHelpers::GetInteger(jCar, "spinningFriction"); car.friction_sound_id = ObjectJsonHelpers::GetInteger(jCar, "frictionSoundId", 255); - car.log_flume_reverser_vehicle_type = ObjectJsonHelpers::GetInteger(jCar, "var58"); + car.log_flume_reverser_vehicle_type = ObjectJsonHelpers::GetInteger(jCar, "logFlumeReverserVehicleType"); car.sound_range = ObjectJsonHelpers::GetInteger(jCar, "soundRange", 255); - car.double_sound_frequency = ObjectJsonHelpers::GetInteger(jCar, "var5A"); + car.double_sound_frequency = ObjectJsonHelpers::GetInteger(jCar, "doubleSoundFrequency"); car.powered_acceleration = ObjectJsonHelpers::GetInteger(jCar, "poweredAcceleration"); car.powered_max_speed = ObjectJsonHelpers::GetInteger(jCar, "poweredMaxSpeed"); car.car_visual = ObjectJsonHelpers::GetInteger(jCar, "carVisual"); @@ -961,7 +969,7 @@ uint8 RideObject::ParseRideType(const std::string &s) { "ghost_train", RIDE_TYPE_GHOST_TRAIN }, { "twister_rc", RIDE_TYPE_TWISTER_ROLLER_COASTER }, { "wooden_rc", RIDE_TYPE_WOODEN_ROLLER_COASTER }, - { "side_friction", RIDE_TYPE_SIDE_FRICTION_ROLLER_COASTER }, + { "side_friction_rc", RIDE_TYPE_SIDE_FRICTION_ROLLER_COASTER }, { "steel_wild_mouse", RIDE_TYPE_STEEL_WILD_MOUSE }, { "multi_dimension_rc", RIDE_TYPE_MULTI_DIMENSION_ROLLER_COASTER }, { "flying_rc", RIDE_TYPE_FLYING_ROLLER_COASTER }, @@ -978,7 +986,7 @@ uint8 RideObject::ParseRideType(const std::string &s) { "flying_saucers", RIDE_TYPE_FLYING_SAUCERS }, { "crooked_house", RIDE_TYPE_CROOKED_HOUSE }, { "monorail_cycles", RIDE_TYPE_MONORAIL_CYCLES }, - { "compact_inverted", RIDE_TYPE_COMPACT_INVERTED_COASTER }, + { "compact_inverted_rc", RIDE_TYPE_COMPACT_INVERTED_COASTER }, { "water_coaster", RIDE_TYPE_WATER_COASTER }, { "air_powered_vertical_rc", RIDE_TYPE_AIR_POWERED_VERTICAL_COASTER }, { "inverted_hairpin_rc", RIDE_TYPE_INVERTED_HAIRPIN_COASTER }, From dfa40ccd461881549ba3652867fef55f9eadd172 Mon Sep 17 00:00:00 2001 From: Ted John Date: Thu, 8 Feb 2018 18:46:01 +0000 Subject: [PATCH 53/93] Read objects from OpenRCT2 data instead of RCT2 --- src/openrct2/object/ObjectRepository.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/openrct2/object/ObjectRepository.cpp b/src/openrct2/object/ObjectRepository.cpp index b0887ac012..0df230554c 100644 --- a/src/openrct2/object/ObjectRepository.cpp +++ b/src/openrct2/object/ObjectRepository.cpp @@ -90,8 +90,8 @@ public: env->GetFilePath(PATHID::CACHE_OBJECTS), std::string(PATTERN), std::vector({ - env->GetDirectoryPath(DIRBASE::USER, DIRID::OBJECT), - env->GetDirectoryPath(DIRBASE::RCT2, DIRID::OBJECT) })) + env->GetDirectoryPath(DIRBASE::OPENRCT2, DIRID::OBJECT), + env->GetDirectoryPath(DIRBASE::USER, DIRID::OBJECT) })) { } @@ -433,9 +433,8 @@ private: } else { - // Commented out temporarily to stop flooding terminal for json-objects branch - // Console::Error::WriteLine("Object conflict: '%s'", conflict->Path); - // Console::Error::WriteLine(" : '%s'", item.Path); + Console::Error::WriteLine("Object conflict: '%s'", conflict->Path); + Console::Error::WriteLine(" : '%s'", item.Path); return false; } } From 83ce94fd9eb1658897837ddccaf2b831ade022ef Mon Sep 17 00:00:00 2001 From: Ted John Date: Thu, 8 Feb 2018 21:31:30 +0000 Subject: [PATCH 54/93] Search for object file, case insensitive --- src/openrct2/object/BannerObject.cpp | 2 +- src/openrct2/object/EntranceObject.cpp | 2 +- src/openrct2/object/FootpathItemObject.cpp | 2 +- src/openrct2/object/FootpathObject.cpp | 2 +- src/openrct2/object/LargeSceneryObject.cpp | 2 +- src/openrct2/object/ObjectFactory.cpp | 2 - src/openrct2/object/ObjectJsonHelpers.cpp | 47 ++++++++++++++++++---- src/openrct2/object/ObjectJsonHelpers.h | 2 +- src/openrct2/object/RideObject.cpp | 2 +- src/openrct2/object/SceneryGroupObject.cpp | 2 +- src/openrct2/object/SmallSceneryObject.cpp | 2 +- src/openrct2/object/WallObject.cpp | 2 +- 12 files changed, 49 insertions(+), 20 deletions(-) diff --git a/src/openrct2/object/BannerObject.cpp b/src/openrct2/object/BannerObject.cpp index 625b8bdb18..749c919f6b 100644 --- a/src/openrct2/object/BannerObject.cpp +++ b/src/openrct2/object/BannerObject.cpp @@ -97,5 +97,5 @@ void BannerObject::ReadJson(IReadObjectContext * context, const json_t * root) SetPrimarySceneryGroup(ObjectJsonHelpers::GetString(json_object_get(properties, "sceneryGroup"))); ObjectJsonHelpers::LoadStrings(root, GetStringTable()); - ObjectJsonHelpers::LoadImages(root, GetImageTable()); + ObjectJsonHelpers::LoadImages(context, root, GetImageTable()); } diff --git a/src/openrct2/object/EntranceObject.cpp b/src/openrct2/object/EntranceObject.cpp index c49b213b93..fc1737a63d 100644 --- a/src/openrct2/object/EntranceObject.cpp +++ b/src/openrct2/object/EntranceObject.cpp @@ -73,5 +73,5 @@ void EntranceObject::ReadJson(IReadObjectContext * context, const json_t * root) _legacyType.text_height = json_integer_value(json_object_get(properties, "textHeight")); ObjectJsonHelpers::LoadStrings(root, GetStringTable()); - ObjectJsonHelpers::LoadImages(root, GetImageTable()); + ObjectJsonHelpers::LoadImages(context, root, GetImageTable()); } diff --git a/src/openrct2/object/FootpathItemObject.cpp b/src/openrct2/object/FootpathItemObject.cpp index 78006e1186..97a5fee55e 100644 --- a/src/openrct2/object/FootpathItemObject.cpp +++ b/src/openrct2/object/FootpathItemObject.cpp @@ -118,5 +118,5 @@ void FootpathItemObject::ReadJson(IReadObjectContext * context, const json_t * r { "isTelevision", PATH_BIT_FLAG_IS_QUEUE_SCREEN }}); ObjectJsonHelpers::LoadStrings(root, GetStringTable()); - ObjectJsonHelpers::LoadImages(root, GetImageTable()); + ObjectJsonHelpers::LoadImages(context, root, GetImageTable()); } diff --git a/src/openrct2/object/FootpathObject.cpp b/src/openrct2/object/FootpathObject.cpp index 9595b7911d..3fd27b6c5a 100644 --- a/src/openrct2/object/FootpathObject.cpp +++ b/src/openrct2/object/FootpathObject.cpp @@ -83,5 +83,5 @@ void FootpathObject::ReadJson(IReadObjectContext * context, const json_t * root) { "editorOnly", FOOTPATH_ENTRY_FLAG_SHOW_ONLY_IN_SCENARIO_EDITOR } }); ObjectJsonHelpers::LoadStrings(root, GetStringTable()); - ObjectJsonHelpers::LoadImages(root, GetImageTable()); + ObjectJsonHelpers::LoadImages(context, root, GetImageTable()); } diff --git a/src/openrct2/object/LargeSceneryObject.cpp b/src/openrct2/object/LargeSceneryObject.cpp index cff381489c..2c1aa6fcd0 100644 --- a/src/openrct2/object/LargeSceneryObject.cpp +++ b/src/openrct2/object/LargeSceneryObject.cpp @@ -163,7 +163,7 @@ void LargeSceneryObject::ReadJson(IReadObjectContext * context, const json_t * r SetPrimarySceneryGroup(ObjectJsonHelpers::GetString(json_object_get(properties, "sceneryGroup"))); ObjectJsonHelpers::LoadStrings(root, GetStringTable()); - ObjectJsonHelpers::LoadImages(root, GetImageTable()); + ObjectJsonHelpers::LoadImages(context, root, GetImageTable()); } std::vector LargeSceneryObject::ReadJsonTiles(const json_t * jTiles) diff --git a/src/openrct2/object/ObjectFactory.cpp b/src/openrct2/object/ObjectFactory.cpp index 1c276f5a04..13fb451099 100644 --- a/src/openrct2/object/ObjectFactory.cpp +++ b/src/openrct2/object/ObjectFactory.cpp @@ -129,8 +129,6 @@ namespace ObjectFactory } catch (const std::exception &) { - Console::Error::WriteLine("Unable to open or read '%s'", path); - delete result; result = nullptr; } diff --git a/src/openrct2/object/ObjectJsonHelpers.cpp b/src/openrct2/object/ObjectJsonHelpers.cpp index 647b52beec..d7dab5077d 100644 --- a/src/openrct2/object/ObjectJsonHelpers.cpp +++ b/src/openrct2/object/ObjectJsonHelpers.cpp @@ -20,6 +20,8 @@ #include #include #include "../Context.h" +#include "../core/File.h" +#include "../core/FileScanner.h" #include "../core/Math.hpp" #include "../core/Memory.hpp" #include "../core/Path.hpp" @@ -205,12 +207,36 @@ namespace ObjectJsonHelpers return result; } - static std::vector LoadObjectImages(const std::string &name, uint32 start, uint32 end) + static std::string FindLegacyObject(const std::string &name) { - std::vector result; const auto env = GetContext()->GetPlatformEnvironment(); auto objectsPath = env->GetDirectoryPath(DIRBASE::RCT2, DIRID::OBJECT); auto objectPath = Path::Combine(objectsPath, name); +#ifndef _WIN32 + if (!File::Exists(objectPath)) + { + // UNIX based systems need to search for any files with the same name + // due to case sensitivity. + auto filter = Path::Combine(objectsPath, "*.dat"); + auto scanner = std::unique_ptr(Path::ScanDirectory(filter, false)); + while (scanner->Next()) + { + auto relativePath = scanner->GetPathRelative(); + if (String::Equals(relativePath, name, true)) + { + objectPath = scanner->GetPath(); + break; + } + } + } +#endif + return objectPath; + } + + static std::vector LoadObjectImages(IReadObjectContext * context, const std::string &name, uint32 start, uint32 end) + { + std::vector result; + auto objectPath = FindLegacyObject(name); auto obj = ObjectFactory::CreateObjectFromLegacyFile(objectPath.c_str()); if (obj != nullptr) { @@ -230,14 +256,19 @@ namespace ObjectJsonHelpers } else { - log_warning("Unable to open '%s'", objectPath.c_str()); + std::string msg = "Unable to open '" + objectPath + "'"; + context->LogWarning(OBJECT_ERROR_INVALID_PROPERTY, msg.c_str()); } // Add place holders auto placeHolders = (size_t)(end - start) - result.size(); if (placeHolders > 0) { - log_warning("Adding %d placeholders", placeHolders); + if (obj != nullptr) + { + std::string msg = "Adding " + std::to_string(placeHolders) + " placeholders"; + context->LogWarning(OBJECT_ERROR_INVALID_PROPERTY, msg.c_str()); + } for (size_t i = 0; i < placeHolders; i++) { auto g1 = rct_g1_element{}; @@ -247,7 +278,7 @@ namespace ObjectJsonHelpers return result; } - static std::vector ParseImages(std::string s) + static std::vector ParseImages(IReadObjectContext * context, std::string s) { std::vector result; if (s.empty()) @@ -293,7 +324,7 @@ namespace ObjectJsonHelpers imgEnd = range.back(); } } - return LoadObjectImages(name, imgStart, imgEnd); + return LoadObjectImages(context, name, imgStart, imgEnd); } return result; } @@ -332,13 +363,13 @@ namespace ObjectJsonHelpers } } - void LoadImages(const json_t * root, ImageTable &imageTable) + void LoadImages(IReadObjectContext * context, const json_t * root, ImageTable &imageTable) { auto jsonImages = json_object_get(root, "images"); auto imageElements = GetJsonStringArray(jsonImages); for (const auto &ie : imageElements) { - auto images = ParseImages(ie); + auto images = ParseImages(context, ie); for (const auto &g1 : images) { imageTable.AddImage(&g1); diff --git a/src/openrct2/object/ObjectJsonHelpers.h b/src/openrct2/object/ObjectJsonHelpers.h index 4a0761db89..8daa454f82 100644 --- a/src/openrct2/object/ObjectJsonHelpers.h +++ b/src/openrct2/object/ObjectJsonHelpers.h @@ -39,7 +39,7 @@ namespace ObjectJsonHelpers uint8 ParseCursor(const std::string &s, uint8 defaultValue); rct_object_entry ParseObjectEntry(const std::string & s); void LoadStrings(const json_t * root, StringTable &stringTable); - void LoadImages(const json_t * root, ImageTable &imageTable); + void LoadImages(IReadObjectContext * context, const json_t * root, ImageTable &imageTable); template T GetFlags(const json_t * obj, std::initializer_list> list) diff --git a/src/openrct2/object/RideObject.cpp b/src/openrct2/object/RideObject.cpp index 58f30998b0..3d86ffd991 100644 --- a/src/openrct2/object/RideObject.cpp +++ b/src/openrct2/object/RideObject.cpp @@ -668,7 +668,7 @@ void RideObject::ReadJson(IReadObjectContext * context, const json_t * root) { "disablePainting", RIDE_ENTRY_FLAG_DISABLE_COLOUR_TAB } }); ObjectJsonHelpers::LoadStrings(root, GetStringTable()); - ObjectJsonHelpers::LoadImages(root, GetImageTable()); + ObjectJsonHelpers::LoadImages(context, root, GetImageTable()); } void RideObject::ReadJsonVehicleInfo(IReadObjectContext * context, const json_t * properties) diff --git a/src/openrct2/object/SceneryGroupObject.cpp b/src/openrct2/object/SceneryGroupObject.cpp index d6ea8d6902..7d88c4171f 100644 --- a/src/openrct2/object/SceneryGroupObject.cpp +++ b/src/openrct2/object/SceneryGroupObject.cpp @@ -144,7 +144,7 @@ void SceneryGroupObject::ReadJson(IReadObjectContext * context, const json_t * r } ObjectJsonHelpers::LoadStrings(root, GetStringTable()); - ObjectJsonHelpers::LoadImages(root, GetImageTable()); + ObjectJsonHelpers::LoadImages(context, root, GetImageTable()); } uint32 SceneryGroupObject::ReadJsonEntertainerCostumes(const json_t * jCostumes) diff --git a/src/openrct2/object/SmallSceneryObject.cpp b/src/openrct2/object/SmallSceneryObject.cpp index 17b0ef2d1f..b01b13939e 100644 --- a/src/openrct2/object/SmallSceneryObject.cpp +++ b/src/openrct2/object/SmallSceneryObject.cpp @@ -309,7 +309,7 @@ void SmallSceneryObject::ReadJson(IReadObjectContext * context, const json_t * r SetPrimarySceneryGroup(ObjectJsonHelpers::GetString(json_object_get(properties, "sceneryGroup"))); ObjectJsonHelpers::LoadStrings(root, GetStringTable()); - ObjectJsonHelpers::LoadImages(root, GetImageTable()); + ObjectJsonHelpers::LoadImages(context, root, GetImageTable()); } std::vector SmallSceneryObject::ReadJsonFrameOffsets(const json_t * jFrameOffsets) diff --git a/src/openrct2/object/WallObject.cpp b/src/openrct2/object/WallObject.cpp index 4da70af90b..c82da14b82 100644 --- a/src/openrct2/object/WallObject.cpp +++ b/src/openrct2/object/WallObject.cpp @@ -145,5 +145,5 @@ void WallObject::ReadJson(IReadObjectContext * context, const json_t * root) } ObjectJsonHelpers::LoadStrings(root, GetStringTable()); - ObjectJsonHelpers::LoadImages(root, GetImageTable()); + ObjectJsonHelpers::LoadImages(context, root, GetImageTable()); } From e7408f188cffe9c3663babdf5f891444824004e0 Mon Sep 17 00:00:00 2001 From: Gymnasiast Date: Thu, 8 Feb 2018 23:38:28 +0100 Subject: [PATCH 55/93] Fix train dropdown not being shown --- src/openrct2/object/RideObject.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/openrct2/object/RideObject.cpp b/src/openrct2/object/RideObject.cpp index 3d86ffd991..8619cbc049 100644 --- a/src/openrct2/object/RideObject.cpp +++ b/src/openrct2/object/RideObject.cpp @@ -675,7 +675,7 @@ void RideObject::ReadJsonVehicleInfo(IReadObjectContext * context, const json_t { _legacyType.min_cars_in_train = json_integer_value(json_object_get(properties, "minCarsPerTrain")); _legacyType.max_cars_in_train = json_integer_value(json_object_get(properties, "maxCarsPerTrain")); - _legacyType.cars_per_flat_ride = json_integer_value(json_object_get(properties, "carsPerFlatRide")); + _legacyType.cars_per_flat_ride = ObjectJsonHelpers::GetInteger(properties, "carsPerFlatRide", 255); _legacyType.zero_cars = json_integer_value(json_object_get(properties, "numEmptyCars")); // Train formation from car indices From c465b35037c898963f2234b2dff5c69ce86456f3 Mon Sep 17 00:00:00 2001 From: Ted John Date: Sat, 10 Feb 2018 15:24:20 +0000 Subject: [PATCH 56/93] Download and distribute objects --- CMakeLists.txt | 10 ++++++++++ openrct2.proj | 11 +++++++++++ 2 files changed, 21 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index ac635d4ebc..3158cb665a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,10 +16,14 @@ set(CMAKE_MACOSX_RPATH 1) set(TITLE_SEQUENCE_URL "https://github.com/OpenRCT2/title-sequences/releases/download/v0.1.2/title-sequence-v0.1.2.zip") set(TITLE_SEQUENCE_SHA1 "1136ef92bfb05cd1cba9831ba6dc4a653d87a246") +set(OBJECTS_URL "https://github.com/OpenRCT2/objects/releases/download/v1.0-beta.2/objects.zip") +set(OBJECTS_SHA1 "4cc7b67705107f9ee07eec4d6dd3e4786056ddd1") + option(FORCE32 "Force 32-bit build. It will add `-m32` to compiler flags.") option(WITH_TESTS "Build tests") option(PORTABLE "Create a portable build (-rpath=$ORIGIN)" OFF) option(DOWNLOAD_TITLE_SEQUENCES "Download title sequences during installation." ON) +option(DOWNLOAD_OBJECTS "Download objects during installation." ON) # Options option(STATIC "Create a static build.") @@ -209,6 +213,12 @@ if (DOWNLOAD_TITLE_SEQUENCES) file(REMOVE \$ENV{DESTDIR}${CMAKE_INSTALL_FULL_DATADIR}/${PROJECT}/title/title-sequences.zip)\n\ endif ()") endif () +if (DOWNLOAD_OBJECTS) + set(OBJECT_DIR "\$ENV{DESTDIR}${CMAKE_INSTALL_FULL_DATADIR}/${PROJECT}/object") + install(CODE "file(DOWNLOAD ${OBJECTS_URL} ${OBJECT_DIR}/objects.zip EXPECTED_HASH SHA1=${OBJECTS_SHA1} SHOW_PROGRESS)") + install(CODE "execute_process(COMMAND \"${CMAKE_COMMAND}\" -E chdir ${OBJECT_DIR}/ \"${CMAKE_COMMAND}\" -E tar xvf objects.zip)") + install(CODE "file(REMOVE ${OBJECT_DIR}/objects.zip)") +endif () install(TARGETS "libopenrct2" LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}") install(TARGETS "openrct2" RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}") diff --git a/openrct2.proj b/openrct2.proj index f2ea557a4e..879f650fd1 100644 --- a/openrct2.proj +++ b/openrct2.proj @@ -71,6 +71,8 @@ 667f873ab7a4d246062565fad32fb6d8e203ee73 https://github.com/OpenRCT2/title-sequences/releases/download/v0.1.2/title-sequence-v0.1.2.zip 1136ef92bfb05cd1cba9831ba6dc4a653d87a246 + https://github.com/OpenRCT2/objects/releases/download/v1.0-beta.2/objects.zip + 4cc7b67705107f9ee07eec4d6dd3e4786056ddd1 @@ -214,6 +216,15 @@ OutputDirectory="$(TargetDir)data\title" /> + + + + + Date: Sat, 10 Feb 2018 20:56:36 +0000 Subject: [PATCH 57/93] Do not load images for objects if in headless mode --- src/openrct2/object/Object.h | 2 ++ src/openrct2/object/ObjectFactory.cpp | 28 ++++++++++++----------- src/openrct2/object/ObjectJsonHelpers.cpp | 18 ++++++++------- 3 files changed, 27 insertions(+), 21 deletions(-) diff --git a/src/openrct2/object/Object.h b/src/openrct2/object/Object.h index 05e93481fb..e86a191ce7 100644 --- a/src/openrct2/object/Object.h +++ b/src/openrct2/object/Object.h @@ -119,6 +119,8 @@ interface IReadObjectContext { virtual ~IReadObjectContext() = default; + virtual bool ShouldLoadImages() abstract; + virtual void LogWarning(uint32 code, const utf8 * text) abstract; virtual void LogError(uint32 code, const utf8 * text) abstract; }; diff --git a/src/openrct2/object/ObjectFactory.cpp b/src/openrct2/object/ObjectFactory.cpp index 13fb451099..6d4ee6ad2c 100644 --- a/src/openrct2/object/ObjectFactory.cpp +++ b/src/openrct2/object/ObjectFactory.cpp @@ -20,6 +20,7 @@ #include "../core/Memory.hpp" #include "../core/MemoryStream.h" #include "../core/String.hpp" +#include "../OpenRCT2.h" #include "../rct12/SawyerChunkReader.h" #include "BannerObject.h" #include "EntranceObject.h" @@ -40,23 +41,24 @@ class ReadObjectContext : public IReadObjectContext { private: - utf8 * _objectName; - bool _wasWarning = false; - bool _wasError = false; + std::string _objectName; + bool _loadImages; + bool _wasWarning = false; + bool _wasError = false; public: bool WasWarning() const { return _wasWarning; } bool WasError() const { return _wasError; } - explicit ReadObjectContext(const utf8 * objectFileName) + ReadObjectContext(const std::string &objectName, bool loadImages) + : _objectName(objectName), + _loadImages(loadImages) { - _objectName = String::Duplicate(objectFileName); } - ~ReadObjectContext() override + bool ShouldLoadImages() override { - Memory::Free(_objectName); - _objectName = nullptr; + return _loadImages; } void LogWarning(uint32 code, const utf8 * text) override @@ -65,7 +67,7 @@ public: if (!String::IsNullOrEmpty(text)) { - Console::Error::WriteLine("[%s] Warning: %s", _objectName, text); + Console::Error::WriteLine("[%s] Warning: %s", _objectName.c_str(), text); } } @@ -75,7 +77,7 @@ public: if (!String::IsNullOrEmpty(text)) { - Console::Error::WriteLine("[%s] Error: %s", _objectName, text); + Console::Error::WriteLine("[%s] Error: %s", _objectName.c_str(), text); } } }; @@ -120,7 +122,7 @@ namespace ObjectFactory log_verbose(" size: %zu", chunk->GetLength()); auto chunkStream = MemoryStream(chunk->GetData(), chunk->GetLength()); - auto readContext = ReadObjectContext(objectName); + auto readContext = ReadObjectContext(objectName, !gOpenRCT2Headless); ReadObjectLegacy(result, &readContext, &chunkStream); if (readContext.WasError()) { @@ -146,7 +148,7 @@ namespace ObjectFactory utf8 objectName[DAT_NAME_LENGTH + 1]; object_entry_get_name_fixed(objectName, sizeof(objectName), entry); - auto readContext = ReadObjectContext(objectName); + auto readContext = ReadObjectContext(objectName, !gOpenRCT2Headless); auto chunkStream = MemoryStream(data, dataSize); ReadObjectLegacy(result, &readContext, &chunkStream); @@ -247,7 +249,7 @@ namespace ObjectFactory memcpy(entry.name, originalName.c_str(), minLength); result = CreateObject(entry); - auto readContext = ReadObjectContext(id); + auto readContext = ReadObjectContext(id, !gOpenRCT2Headless); result->ReadJson(&readContext, jRoot); if (readContext.WasError()) { diff --git a/src/openrct2/object/ObjectJsonHelpers.cpp b/src/openrct2/object/ObjectJsonHelpers.cpp index d7dab5077d..153e8cb8ce 100644 --- a/src/openrct2/object/ObjectJsonHelpers.cpp +++ b/src/openrct2/object/ObjectJsonHelpers.cpp @@ -311,7 +311,6 @@ namespace ObjectJsonHelpers auto rangeStart = name.find('['); auto imgStart = 0; auto imgEnd = INT16_MAX; - //auto range = std::vector({ 0 }); if (rangeStart != std::string::npos) { auto rangeString = name.substr(rangeStart); @@ -365,15 +364,18 @@ namespace ObjectJsonHelpers void LoadImages(IReadObjectContext * context, const json_t * root, ImageTable &imageTable) { - auto jsonImages = json_object_get(root, "images"); - auto imageElements = GetJsonStringArray(jsonImages); - for (const auto &ie : imageElements) + if (context->ShouldLoadImages()) { - auto images = ParseImages(context, ie); - for (const auto &g1 : images) + auto jsonImages = json_object_get(root, "images"); + auto imageElements = GetJsonStringArray(jsonImages); + for (const auto &ie : imageElements) { - imageTable.AddImage(&g1); - std::free(g1.offset); + auto images = ParseImages(context, ie); + for (const auto &g1 : images) + { + imageTable.AddImage(&g1); + std::free(g1.offset); + } } } } From f91449190a6a5c294ddfa397ae2af5a17df7bad2 Mon Sep 17 00:00:00 2001 From: Ted John Date: Sat, 10 Feb 2018 21:43:26 +0000 Subject: [PATCH 58/93] Allow game to run without RCT2 install path --- src/openrct2/Context.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/openrct2/Context.cpp b/src/openrct2/Context.cpp index 09ec0ce153..c0329090a2 100644 --- a/src/openrct2/Context.cpp +++ b/src/openrct2/Context.cpp @@ -301,12 +301,15 @@ namespace OpenRCT2 // return false; // } //This comment was relocated so it would stay where it was in relation to the following lines of code. - auto rct2InstallPath = GetOrPromptRCT2Path(); - if (rct2InstallPath.empty()) + if (!gOpenRCT2Headless) { - return false; + auto rct2InstallPath = GetOrPromptRCT2Path(); + if (rct2InstallPath.empty()) + { + return false; + } + _env->SetBasePath(DIRBASE::RCT2, rct2InstallPath); } - _env->SetBasePath(DIRBASE::RCT2, rct2InstallPath); _objectRepository = CreateObjectRepository(_env); _objectManager = CreateObjectManager(_objectRepository); From f43937a0fdc91dde01d5014c9d5e87dc99a8c62f Mon Sep 17 00:00:00 2001 From: Gymnasiast Date: Mon, 12 Feb 2018 20:20:21 +0100 Subject: [PATCH 59/93] Fix initial car index values --- src/openrct2/object/RideObject.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/openrct2/object/RideObject.cpp b/src/openrct2/object/RideObject.cpp index 8619cbc049..5ba532d02d 100644 --- a/src/openrct2/object/RideObject.cpp +++ b/src/openrct2/object/RideObject.cpp @@ -687,6 +687,12 @@ void RideObject::ReadJsonVehicleInfo(IReadObjectContext * context, const json_t _legacyType.flags |= RIDE_ENTRY_FLAG_VEHICLE_TAB_SCALE_HALF; } + // 0xFF means N/A. + _legacyType.front_vehicle = 0xFF; + _legacyType.second_vehicle = 0xFF; + _legacyType.third_vehicle = 0xFF; + _legacyType.rear_vehicle = 0xFF; + auto headCars = ObjectJsonHelpers::GetJsonIntegerArray(json_object_get(properties, "headCars")); if (headCars.size() >= 1) { From 195ca240867774e1c2ef8db825e04cfa708702c6 Mon Sep 17 00:00:00 2001 From: Gymnasiast Date: Mon, 12 Feb 2018 20:46:09 +0100 Subject: [PATCH 60/93] Fix crash when spawning flat rides --- src/openrct2/object/RideObject.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/openrct2/object/RideObject.cpp b/src/openrct2/object/RideObject.cpp index 5ba532d02d..801f679aea 100644 --- a/src/openrct2/object/RideObject.cpp +++ b/src/openrct2/object/RideObject.cpp @@ -673,8 +673,8 @@ void RideObject::ReadJson(IReadObjectContext * context, const json_t * root) void RideObject::ReadJsonVehicleInfo(IReadObjectContext * context, const json_t * properties) { - _legacyType.min_cars_in_train = json_integer_value(json_object_get(properties, "minCarsPerTrain")); - _legacyType.max_cars_in_train = json_integer_value(json_object_get(properties, "maxCarsPerTrain")); + _legacyType.min_cars_in_train = ObjectJsonHelpers::GetInteger(properties, "minCarsPerTrain", 1); + _legacyType.max_cars_in_train = ObjectJsonHelpers::GetInteger(properties, "maxCarsPerTrain", 1); _legacyType.cars_per_flat_ride = ObjectJsonHelpers::GetInteger(properties, "carsPerFlatRide", 255); _legacyType.zero_cars = json_integer_value(json_object_get(properties, "numEmptyCars")); From 860127e898e37c5b002a65bd52ea15a0ed41d2ea Mon Sep 17 00:00:00 2001 From: Gymnasiast Date: Mon, 12 Feb 2018 20:48:22 +0100 Subject: [PATCH 61/93] Fix rides selling balloons --- src/openrct2/object/RideObject.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/openrct2/object/RideObject.cpp b/src/openrct2/object/RideObject.cpp index 801f679aea..ef5d2059d2 100644 --- a/src/openrct2/object/RideObject.cpp +++ b/src/openrct2/object/RideObject.cpp @@ -555,6 +555,10 @@ void RideObject::ReadJson(IReadObjectContext * context, const json_t * root) _legacyType.max_height = ObjectJsonHelpers::GetInteger(properties, "maxHeight"); + // This needs to be set for both shops/facilities _and_ regular rides. + _legacyType.shop_item = SHOP_ITEM_NONE; + _legacyType.shop_item_secondary = SHOP_ITEM_NONE; + if (IsRideTypeShopOrFacility(_legacyType.ride_type[0])) { // Standard car info for a shop @@ -572,8 +576,6 @@ void RideObject::ReadJson(IReadObjectContext * context, const json_t * root) // Shop item auto rideSells = ObjectJsonHelpers::GetJsonStringArray(json_object_get(json_object_get(root, "properties"), "sells")); - _legacyType.shop_item = SHOP_ITEM_NONE; - _legacyType.shop_item_secondary = SHOP_ITEM_NONE; if (rideSells.size() >= 1) { _legacyType.shop_item = ParseShopItem(rideSells[0]); From baedac28105460262e691706b2a0e1e6c7877de2 Mon Sep 17 00:00:00 2001 From: Michael Steenbeek Date: Mon, 19 Mar 2018 12:08:35 +0100 Subject: [PATCH 62/93] Fix Xcode project --- OpenRCT2.xcodeproj/project.pbxproj | 48 +++--------------------------- 1 file changed, 4 insertions(+), 44 deletions(-) diff --git a/OpenRCT2.xcodeproj/project.pbxproj b/OpenRCT2.xcodeproj/project.pbxproj index 5b3698965a..8277955949 100644 --- a/OpenRCT2.xcodeproj/project.pbxproj +++ b/OpenRCT2.xcodeproj/project.pbxproj @@ -23,46 +23,10 @@ /* Begin PBXBuildFile section */ 4C3B4236205914F7000C5BB7 /* InGameConsole.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C3B4234205914F7000C5BB7 /* InGameConsole.cpp */; }; 4C3B423820591513000C5BB7 /* StdInOutConsole.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C3B423720591513000C5BB7 /* StdInOutConsole.cpp */; }; + 4C1A53ED205FD1A0000F8EF5 /* SceneryObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C1A53EC205FD19F000F8EF5 /* SceneryObject.cpp */; }; 4C93F1AD1F8CD9F000A9330D /* Input.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C93F1AC1F8CD9F000A9330D /* Input.cpp */; }; 4C93F1AF1F8CD9F600A9330D /* KeyboardShortcut.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C93F1AE1F8CD9F600A9330D /* KeyboardShortcut.cpp */; }; - 4C93F1BA1F8E185600A9330D /* Award.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C93F1B01F8E185600A9330D /* Award.cpp */; }; - 4C93F1BB1F8E185600A9330D /* Finance.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C93F1B21F8E185600A9330D /* Finance.cpp */; }; - 4C93F1BC1F8E185600A9330D /* Marketing.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C93F1B41F8E185600A9330D /* Marketing.cpp */; }; - 4C93F1BD1F8E185600A9330D /* NewsItem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C93F1B61F8E185600A9330D /* NewsItem.cpp */; }; - 4C93F1BE1F8E185600A9330D /* Research.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C93F1B81F8E185600A9330D /* Research.cpp */; }; - 4CB832AB1EFFB8D100B88761 /* ttf_sdlport.c in Sources */ = {isa = PBXBuildFile; fileRef = 4CB832A81EFFB8D100B88761 /* ttf_sdlport.c */; }; - 4CC4B8E41FE00C4200660D62 /* CmdlineSprite.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CC4B8E21FE00C4100660D62 /* CmdlineSprite.cpp */; }; - 4CC4B8E71FE00C4E00660D62 /* Diagnostic.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CC4B8E51FE00C4E00660D62 /* Diagnostic.cpp */; }; - 4CC4B8ED1FE00C5D00660D62 /* Intro.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CC4B8EA1FE00C5D00660D62 /* Intro.cpp */; }; - 4CE462411FD0710E0001CD98 /* Game.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CE4623F1FD0710E0001CD98 /* Game.cpp */; }; - 4CE462451FD161360001CD98 /* Platform.Android.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CE462441FD161360001CD98 /* Platform.Android.cpp */; }; - 4CE4624A1FD1613D0001CD98 /* Platform.Linux.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CE462461FD1613D0001CD98 /* Platform.Linux.cpp */; }; - 4CE4624B1FD1613D0001CD98 /* Platform.macOS.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CE462471FD1613D0001CD98 /* Platform.macOS.cpp */; }; - 4CE4624C1FD1613D0001CD98 /* Platform.Posix.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CE462481FD1613D0001CD98 /* Platform.Posix.cpp */; }; - 4CE4624D1FD1613D0001CD98 /* Platform.Win32.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CE462491FD1613D0001CD98 /* Platform.Win32.cpp */; }; 4CE9AAAD1FDA7B14004093C6 /* ObjectJsonHelpers.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CE9AAAB1FDA7B14004093C6 /* ObjectJsonHelpers.cpp */; }; - 4CF788C01F1B787700C611BF /* Painter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CF788BE1F1B787700C611BF /* Painter.cpp */; }; - 4CFBCD5E1F27CD8000D74FB6 /* SmallScenery.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CFBCD5D1F27CD8000D74FB6 /* SmallScenery.cpp */; }; - 4CFE4E801F90A3F1005243C2 /* Peep.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CFE4E7B1F90A3F1005243C2 /* Peep.cpp */; }; - 4CFE4E811F90A3F1005243C2 /* PeepData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CFE4E7D1F90A3F1005243C2 /* PeepData.cpp */; }; - 4CFE4E821F90A3F1005243C2 /* Staff.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CFE4E7E1F90A3F1005243C2 /* Staff.cpp */; }; - 4CFE4E851F90AF41005243C2 /* Vehicle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CFE4E831F90AF41005243C2 /* Vehicle.cpp */; }; - 4CFE4E891F950164005243C2 /* TrackData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CFE4E861F950164005243C2 /* TrackData.cpp */; }; - 4CFE4E8A1F950164005243C2 /* TrackDataOld.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CFE4E881F950164005243C2 /* TrackDataOld.cpp */; }; - 4CFE4E901F9625B0005243C2 /* Track.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CFE4E8E1F9625B0005243C2 /* Track.cpp */; }; - C606CCC01DB4054000FE4015 /* FunctionCall.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C606CCAE1DB4054000FE4015 /* FunctionCall.cpp */; }; - C606CCC11DB4054000FE4015 /* generate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C606CCB01DB4054000FE4015 /* generate.cpp */; }; - C606CCC41DB4054000FE4015 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C606CCB41DB4054000FE4015 /* main.cpp */; }; - C606CCC51DB4054000FE4015 /* PaintIntercept.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C606CCB51DB4054000FE4015 /* PaintIntercept.cpp */; }; - C606CCC61DB4054000FE4015 /* Printer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C606CCB61DB4054000FE4015 /* Printer.cpp */; }; - C606CCC71DB4054000FE4015 /* String.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C606CCB81DB4054000FE4015 /* String.cpp */; }; - C606CCC81DB4054000FE4015 /* TestTrack.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C606CCBA1DB4054000FE4015 /* TestTrack.cpp */; }; - C606CCC91DB4054000FE4015 /* Utils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C606CCBC1DB4054000FE4015 /* Utils.cpp */; }; - C606CCCE1DB427A000FE4015 /* GeneralSupportHeightCall.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C606CCCA1DB427A000FE4015 /* GeneralSupportHeightCall.cpp */; }; - C606CCCF1DB427A000FE4015 /* SegmentSupportHeightCall.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C606CCCC1DB427A000FE4015 /* SegmentSupportHeightCall.cpp */; }; - C606CCD21DB4D7C800FE4015 /* SideTunnelCall.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C606CCD01DB4D7C800FE4015 /* SideTunnelCall.cpp */; }; - C606CCD51DB4DD6C00FE4015 /* VerticalTunnelCall.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C606CCD31DB4DD6C00FE4015 /* VerticalTunnelCall.cpp */; }; - C606CD261DB5120C00FE4015 /* TestPaint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C606CD231DB5120900FE4015 /* TestPaint.cpp */; }; C61ADB1F1FB6A0A70024F2EF /* TopToolbar.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C61ADB1E1FB6A0A60024F2EF /* TopToolbar.cpp */; }; C61ADB211FB7DC060024F2EF /* Scenery.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C61ADB201FB7DC060024F2EF /* Scenery.cpp */; }; C61ADB231FBBCB8B0024F2EF /* GameBottomToolbar.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C61ADB221FBBCB8A0024F2EF /* GameBottomToolbar.cpp */; }; @@ -627,6 +591,7 @@ 4C3B4234205914F7000C5BB7 /* InGameConsole.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InGameConsole.cpp; sourceTree = ""; }; 4C3B4235205914F7000C5BB7 /* InGameConsole.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InGameConsole.h; sourceTree = ""; }; 4C3B423720591513000C5BB7 /* StdInOutConsole.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StdInOutConsole.cpp; sourceTree = ""; }; + 4C1A53EC205FD19F000F8EF5 /* SceneryObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SceneryObject.cpp; sourceTree = ""; }; 4C4C1E971F58226500560300 /* TrackDesign.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TrackDesign.cpp; sourceTree = ""; }; 4C4C1E991F5832AA00560300 /* TrackDesign.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TrackDesign.h; sourceTree = ""; }; 4C5DFF401FAC69D200CB093A /* Date.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Date.cpp; sourceTree = ""; }; @@ -887,9 +852,6 @@ 4CE462491FD1613D0001CD98 /* Platform.Win32.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Platform.Win32.cpp; sourceTree = ""; }; 4CE9AAAB1FDA7B14004093C6 /* ObjectJsonHelpers.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ObjectJsonHelpers.cpp; sourceTree = ""; }; 4CE9AAAC1FDA7B14004093C6 /* ObjectJsonHelpers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ObjectJsonHelpers.h; sourceTree = ""; }; - 4CF788BE1F1B787700C611BF /* Painter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Painter.cpp; sourceTree = ""; }; - 4CF788BF1F1B787700C611BF /* Painter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Painter.h; sourceTree = ""; }; - 4CFBCD5D1F27CD8000D74FB6 /* SmallScenery.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SmallScenery.cpp; sourceTree = ""; }; 4CFE4E7B1F90A3F1005243C2 /* Peep.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Peep.cpp; sourceTree = ""; }; 4CFE4E7C1F90A3F1005243C2 /* Peep.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Peep.h; sourceTree = ""; }; 4CFE4E7D1F90A3F1005243C2 /* PeepData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PeepData.cpp; sourceTree = ""; }; @@ -2136,6 +2098,7 @@ F76C84271EC4E7CC00FA49E2 /* RideObject.h */, F76C84281EC4E7CC00FA49E2 /* SceneryGroupObject.cpp */, F76C84291EC4E7CC00FA49E2 /* SceneryGroupObject.h */, + 4C1A53EC205FD19F000F8EF5 /* SceneryObject.cpp */, F76C842A1EC4E7CC00FA49E2 /* SceneryObject.h */, F76C842B1EC4E7CC00FA49E2 /* SmallSceneryObject.cpp */, F76C842C1EC4E7CC00FA49E2 /* SmallSceneryObject.h */, @@ -3048,6 +3011,7 @@ C68313C81FDB4ED4006DB3D8 /* MouseInput.cpp in Sources */, C68878C920289B710084B384 /* TextureCache.cpp in Sources */, C61ADB1F1FB6A0A70024F2EF /* TopToolbar.cpp in Sources */, + 4C1A53ED205FD1A0000F8EF5 /* SceneryObject.cpp in Sources */, F76C887B1EC5324E00FA49E2 /* FileAudioSource.cpp in Sources */, C68878CA20289B710084B384 /* TransparencyDepth.cpp in Sources */, C64644FD1F3FA4120026AC2D /* Land.cpp in Sources */, @@ -3088,11 +3052,7 @@ C68313D51FDB4F4C006DB3D8 /* Graph.cpp in Sources */, C685E51D1F8907850090598F /* Research.cpp in Sources */, C64644FB1F3FA4120026AC2D /* EditorScenarioOptions.cpp in Sources */, - 4C6A66AB1FE2787700694CB6 /* SmallScenery.cpp in Sources */, 4CE9AAAD1FDA7B14004093C6 /* ObjectJsonHelpers.cpp in Sources */, - F775F5371EE3724F001F00E7 /* DummyAudioContext.cpp in Sources */, - 4C5DFF421FAC69D200CB093A /* Date.cpp in Sources */, - 4C93F13C1F8B744400A9330D /* BolligerMabillardTrack.cpp in Sources */, C654DF321F69C0430040F43D /* InstallTrack.cpp in Sources */, C64644FF1F3FA4120026AC2D /* StaffList.cpp in Sources */, C6D2BEE81F9BAACE008B557C /* MazeConstruction.cpp in Sources */, From be000f9ba614cecb32bd4f0a0ba75bcb19a7ab15 Mon Sep 17 00:00:00 2001 From: Ted John Date: Mon, 19 Mar 2018 17:02:48 +0000 Subject: [PATCH 63/93] Sort string table when loading strings from JSON --- src/openrct2/object/ObjectJsonHelpers.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/openrct2/object/ObjectJsonHelpers.cpp b/src/openrct2/object/ObjectJsonHelpers.cpp index 153e8cb8ce..2324c75d8a 100644 --- a/src/openrct2/object/ObjectJsonHelpers.cpp +++ b/src/openrct2/object/ObjectJsonHelpers.cpp @@ -360,6 +360,7 @@ namespace ObjectJsonHelpers } } } + stringTable.Sort(); } void LoadImages(IReadObjectContext * context, const json_t * root, ImageTable &imageTable) From 04fecf64e4a3d5fd9878528f6e6459252506d9e3 Mon Sep 17 00:00:00 2001 From: Ted John Date: Tue, 20 Mar 2018 22:47:34 +0000 Subject: [PATCH 64/93] Do not prepend the position data size --- src/openrct2/object/RideObject.cpp | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/openrct2/object/RideObject.cpp b/src/openrct2/object/RideObject.cpp index ef5d2059d2..8406de40df 100644 --- a/src/openrct2/object/RideObject.cpp +++ b/src/openrct2/object/RideObject.cpp @@ -632,17 +632,6 @@ void RideObject::ReadJson(IReadObjectContext * context, const json_t * root) if (numPositions > 0 && numPositions <= std::numeric_limits::max()) { std::vector positionData; - if (numPositions < 255) - { - positionData.push_back(static_cast(numPositions)); - } - else - { - positionData.push_back(-1); - positionData.push_back(static_cast(numPositions & 0xFF)); - positionData.push_back(static_cast(numPositions >> 8)); - } - for (size_t j = 0; j < numPositions; j++) { auto pos = json_integer_value(json_array_get(positions, j)); From 6616ce0a6769e7253e0d64d10935506804175541 Mon Sep 17 00:00:00 2001 From: Ted John Date: Sat, 24 Mar 2018 17:47:42 +0000 Subject: [PATCH 65/93] Load new peep loading position json format --- src/openrct2/object/RideObject.cpp | 84 +++++++++++++++++++++--------- src/openrct2/peep/Peep.cpp | 6 +-- src/openrct2/ride/RideData.cpp | 2 +- src/openrct2/ride/Vehicle.h | 6 ++- 4 files changed, 68 insertions(+), 30 deletions(-) diff --git a/src/openrct2/object/RideObject.cpp b/src/openrct2/object/RideObject.cpp index 8406de40df..2e1da1b3ae 100644 --- a/src/openrct2/object/RideObject.cpp +++ b/src/openrct2/object/RideObject.cpp @@ -285,8 +285,11 @@ void RideObject::Load() set_vehicle_type_image_max_sizes(vehicleEntry, num_images); } } - vehicleEntry->peep_loading_positions = _peepLoadingPositions[i].data(); - vehicleEntry->peep_loading_positions_count = (uint16)_peepLoadingPositions[i].size(); + + if (!_peepLoadingPositions[i].empty()) + { + vehicleEntry->peep_loading_positions = std::move(_peepLoadingPositions[i]); + } } } } @@ -620,27 +623,6 @@ void RideObject::ReadJson(IReadObjectContext * context, const json_t * root) auto availableTrackPieces = ObjectJsonHelpers::GetJsonStringArray(json_object_get(properties, "availableTrackPieces")); _presetColours = ReadJsonCarColours(json_object_get(properties, "carColours")); - - - // Get loading positions - auto loadingPositions = json_object_get(properties, "loadingPositions"); - auto numLoadingPositions = std::min(json_array_size(loadingPositions), 4); - for (size_t i = 0; i < numLoadingPositions; i++) - { - auto positions = json_array_get(loadingPositions, i); - auto numPositions = json_array_size(positions); - if (numPositions > 0 && numPositions <= std::numeric_limits::max()) - { - std::vector positionData; - for (size_t j = 0; j < numPositions; j++) - { - auto pos = json_integer_value(json_array_get(positions, j)); - pos = Math::Clamp(std::numeric_limits::min(), pos, std::numeric_limits::max()); - positionData.push_back(pos); - } - _peepLoadingPositions[i] = std::move(positionData); - } - } } _legacyType.flags |= ObjectJsonHelpers::GetFlags(properties, { @@ -770,6 +752,61 @@ rct_ride_entry_vehicle RideObject::ReadJsonCar(const json_t * jCar) car.draw_order = ObjectJsonHelpers::GetInteger(jCar, "drawOrder"); car.num_vertical_frames_override = ObjectJsonHelpers::GetInteger(jCar, "numVerticalFramesOverride"); + auto& peepLoadingPositions = car.peep_loading_positions; + auto jLoadingPositions = json_object_get(jCar, "loadingPositions"); + if (json_is_array(jLoadingPositions)) + { + auto arr = ObjectJsonHelpers::GetJsonIntegerArray(jLoadingPositions); + for (auto x : arr) + { + peepLoadingPositions.push_back(x); + } + } + else + { + auto jLoadingWaypoints = json_object_get(jCar, "loadingWaypoints"); + if (json_is_array(jLoadingWaypoints)) + { + auto numSegments = ObjectJsonHelpers::GetInteger(jCar, "numSegments"); + if (numSegments == 8) + { + car.flags |= VEHICLE_ENTRY_FLAG_26; + peepLoadingPositions.push_back(0); + } + else if (numSegments == 4) + { + peepLoadingPositions.push_back(1); + } + else + { + peepLoadingPositions.push_back(0); + } + + size_t i; + json_t * route; + json_array_foreach(jLoadingWaypoints, i, route) + { + if (json_is_array(route)) + { + size_t j; + json_t * waypoint; + json_array_foreach(route, j, waypoint) + { + if (json_is_array(waypoint) && json_array_size(waypoint) >= 2) + { + auto x = json_integer_value(json_array_get(waypoint, 0)); + auto y = json_integer_value(json_array_get(waypoint, 1)); + peepLoadingPositions.push_back(x); + peepLoadingPositions.push_back(y); + } + } + peepLoadingPositions.push_back(0); + peepLoadingPositions.push_back(0); + } + } + } + } + auto jFrames = json_object_get(jCar, "frames"); car.sprite_flags = ObjectJsonHelpers::GetFlags(jFrames, { { "flat", VEHICLE_SPRITE_FLAG_FLAT }, @@ -816,7 +853,6 @@ rct_ride_entry_vehicle RideObject::ReadJsonCar(const json_t * jCar) { "VEHICLE_ENTRY_FLAG_VEHICLE_ANIMATION", VEHICLE_ENTRY_FLAG_VEHICLE_ANIMATION }, { "VEHICLE_ENTRY_FLAG_RIDER_ANIMATION", VEHICLE_ENTRY_FLAG_RIDER_ANIMATION }, { "VEHICLE_ENTRY_FLAG_25", VEHICLE_ENTRY_FLAG_25 }, - { "VEHICLE_ENTRY_FLAG_26", VEHICLE_ENTRY_FLAG_26 }, { "VEHICLE_ENTRY_FLAG_SLIDE_SWING", VEHICLE_ENTRY_FLAG_SLIDE_SWING }, { "VEHICLE_ENTRY_FLAG_CHAIRLIFT", VEHICLE_ENTRY_FLAG_CHAIRLIFT }, { "VEHICLE_ENTRY_FLAG_WATER_RIDE", VEHICLE_ENTRY_FLAG_WATER_RIDE }, diff --git a/src/openrct2/peep/Peep.cpp b/src/openrct2/peep/Peep.cpp index 505dee189f..6a207abfe9 100644 --- a/src/openrct2/peep/Peep.cpp +++ b/src/openrct2/peep/Peep.cpp @@ -3021,7 +3021,7 @@ static void peep_update_ride_sub_state_1(rct_peep * peep) if (ride->type != RIDE_TYPE_ENTERPRISE) direction_track *= 2; - if (*vehicle_type->peep_loading_positions == 0) + if (vehicle_type->peep_loading_positions[0] == 0) { direction_track /= 2; cl = 0; @@ -3063,7 +3063,7 @@ static void peep_update_ride_sub_state_1(rct_peep * peep) sint8 load_position = 0; // Safe, in case current seat > number of loading positions - uint16 numSeatPositions = vehicle_type->peep_loading_positions_count; + auto numSeatPositions = vehicle_type->peep_loading_positions.size(); if (numSeatPositions != 0) { size_t loadPositionIndex = numSeatPositions - 1; @@ -3563,7 +3563,7 @@ static void peep_update_ride_sub_state_7(rct_peep * peep) if (ride->type != RIDE_TYPE_ENTERPRISE) station_direction *= 2; - if (*vehicle_type->peep_loading_positions == 0) + if (vehicle_type->peep_loading_positions[0] == 0) { station_direction /= 2; cl = 0; diff --git a/src/openrct2/ride/RideData.cpp b/src/openrct2/ride/RideData.cpp index df604d8573..ae67d56a62 100644 --- a/src/openrct2/ride/RideData.cpp +++ b/src/openrct2/ride/RideData.cpp @@ -1629,7 +1629,7 @@ const rct_ride_entry_vehicle CableLiftVehicle = { /* .effect_visual = */ 1, /* .draw_order = */ 14, /* .num_vertical_frames_override = */ 0, - /* .peep_loading_positions = */ nullptr + /* .peep_loading_positions = */ }; /* rct2: 0x009A0AA0 */ diff --git a/src/openrct2/ride/Vehicle.h b/src/openrct2/ride/Vehicle.h index 828c173376..9301a48d03 100644 --- a/src/openrct2/ride/Vehicle.h +++ b/src/openrct2/ride/Vehicle.h @@ -17,6 +17,7 @@ #ifndef _VEHICLE_H_ #define _VEHICLE_H_ +#include #include "../common.h" #include "../world/Location.hpp" @@ -76,8 +77,9 @@ struct rct_ride_entry_vehicle { uint8 effect_visual; uint8 draw_order; uint8 num_vertical_frames_override; // 0x60 , 0x7A, A custom number that can be used rather than letting RCT2 determine it. Needs the VEHICLE_ENTRY_FLAG_OVERRIDE_NUM_VERTICAL_FRAMES flag to be set. - sint8* peep_loading_positions; // 0x61 , 0x7B - uint16 peep_loading_positions_count; + uint8 pad_61[7]; // 0x61 , 0x7B + + std::vector peep_loading_positions; }; #pragma pack(pop) From 046199c6606210c88005a0e67862e139aafecb67 Mon Sep 17 00:00:00 2001 From: Ted John Date: Sat, 24 Mar 2018 17:51:16 +0000 Subject: [PATCH 66/93] Update objects download version to v1.0-beta.3 --- CMakeLists.txt | 4 ++-- openrct2.proj | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3158cb665a..aeeef42c2f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,8 +16,8 @@ set(CMAKE_MACOSX_RPATH 1) set(TITLE_SEQUENCE_URL "https://github.com/OpenRCT2/title-sequences/releases/download/v0.1.2/title-sequence-v0.1.2.zip") set(TITLE_SEQUENCE_SHA1 "1136ef92bfb05cd1cba9831ba6dc4a653d87a246") -set(OBJECTS_URL "https://github.com/OpenRCT2/objects/releases/download/v1.0-beta.2/objects.zip") -set(OBJECTS_SHA1 "4cc7b67705107f9ee07eec4d6dd3e4786056ddd1") +set(OBJECTS_URL "https://github.com/OpenRCT2/objects/releases/download/v1.0-beta.3/objects.zip") +set(OBJECTS_SHA1 "0cffb52762336036a2366a5c733776a7aeead6bb") option(FORCE32 "Force 32-bit build. It will add `-m32` to compiler flags.") option(WITH_TESTS "Build tests") diff --git a/openrct2.proj b/openrct2.proj index 879f650fd1..99d776b74e 100644 --- a/openrct2.proj +++ b/openrct2.proj @@ -71,8 +71,8 @@ 667f873ab7a4d246062565fad32fb6d8e203ee73 https://github.com/OpenRCT2/title-sequences/releases/download/v0.1.2/title-sequence-v0.1.2.zip 1136ef92bfb05cd1cba9831ba6dc4a653d87a246 - https://github.com/OpenRCT2/objects/releases/download/v1.0-beta.2/objects.zip - 4cc7b67705107f9ee07eec4d6dd3e4786056ddd1 + https://github.com/OpenRCT2/objects/releases/download/v1.0-beta.3/objects.zip + 0cffb52762336036a2366a5c733776a7aeead6bb From 918562f622c2d37e1024fdc573d3231d52e9c216 Mon Sep 17 00:00:00 2001 From: Ted John Date: Sun, 25 Mar 2018 14:30:48 +0100 Subject: [PATCH 67/93] Apply review fixes --- src/openrct2/object/RideObject.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/openrct2/object/RideObject.cpp b/src/openrct2/object/RideObject.cpp index 2e1da1b3ae..b5d4182617 100644 --- a/src/openrct2/object/RideObject.cpp +++ b/src/openrct2/object/RideObject.cpp @@ -732,6 +732,11 @@ rct_ride_entry_vehicle RideObject::ReadJsonCar(const json_t * jCar) car.car_mass = ObjectJsonHelpers::GetInteger(jCar, "mass"); car.tab_height = ObjectJsonHelpers::GetInteger(jCar, "tabOffset"); car.num_seats = ObjectJsonHelpers::GetInteger(jCar, "numSeats"); + if (ObjectJsonHelpers::GetBoolean(jCar, "seatsInPairs")) + { + car.num_seats |= 0x80; + } + car.sprite_width = ObjectJsonHelpers::GetInteger(jCar, "spriteWidth"); car.sprite_height_negative = ObjectJsonHelpers::GetInteger(jCar, "spriteHeightNegative"); car.sprite_height_positive = ObjectJsonHelpers::GetInteger(jCar, "spriteHeightPositive"); @@ -767,11 +772,12 @@ rct_ride_entry_vehicle RideObject::ReadJsonCar(const json_t * jCar) auto jLoadingWaypoints = json_object_get(jCar, "loadingWaypoints"); if (json_is_array(jLoadingWaypoints)) { + car.flags |= VEHICLE_ENTRY_FLAG_26; + auto numSegments = ObjectJsonHelpers::GetInteger(jCar, "numSegments"); if (numSegments == 8) { - car.flags |= VEHICLE_ENTRY_FLAG_26; - peepLoadingPositions.push_back(0); + peepLoadingPositions.push_back(1); } else if (numSegments == 4) { From d1a81b1ade2b55fe8fb5b7be005b1245bde82604 Mon Sep 17 00:00:00 2001 From: Gymnasiast Date: Mon, 26 Mar 2018 22:20:28 +0200 Subject: [PATCH 68/93] Don't set now-unused SEPARATE_RIDE flag --- src/openrct2/object/RideObject.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/openrct2/object/RideObject.cpp b/src/openrct2/object/RideObject.cpp index b5d4182617..e253ecebf6 100644 --- a/src/openrct2/object/RideObject.cpp +++ b/src/openrct2/object/RideObject.cpp @@ -634,7 +634,6 @@ void RideObject::ReadJson(IReadObjectContext * context, const json_t * root) { "playSplashSoundSlide", RIDE_ENTRY_FLAG_PLAY_SPLASH_SOUND_SLIDE }, { "hasShelter", RIDE_ENTRY_FLAG_COVERED_RIDE }, { "limitAirTimeBonus", RIDE_ENTRY_FLAG_LIMIT_AIRTIME_BONUS }, - { "separateRide", RIDE_ENTRY_FLAG_SEPARATE_RIDE }, { "disableBreakdown", RIDE_ENTRY_FLAG_CANNOT_BREAK_DOWN }, { "RIDE_ENTRY_FLAG_16", RIDE_ENTRY_FLAG_16 }, { "RIDE_ENTRY_FLAG_18", RIDE_ENTRY_FLAG_18 }, From 566af0c4f7f948c03db4c131ffdd1873c77a3ba3 Mon Sep 17 00:00:00 2001 From: Gymnasiast Date: Tue, 27 Mar 2018 20:40:50 +0200 Subject: [PATCH 69/93] Remove residual usages of rideEntry->enabledTrackPieces --- src/openrct2-ui/windows/Ride.cpp | 4 ++-- src/openrct2/ride/RideGroupManager.cpp | 8 ++++---- src/openrct2/ride/Track.cpp | 3 +-- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/openrct2-ui/windows/Ride.cpp b/src/openrct2-ui/windows/Ride.cpp index 93259633a0..87da3fdba2 100644 --- a/src/openrct2-ui/windows/Ride.cpp +++ b/src/openrct2-ui/windows/Ride.cpp @@ -3397,8 +3397,8 @@ static void window_ride_operating_invalidate(rct_window *w) ); // Lift hill speed - if ((rideEntry->enabledTrackPieces & (1ULL << TRACK_LIFT_HILL)) && - track_piece_is_available_for_ride_type(ride->type, TRACK_LIFT_HILL)) { + if (track_piece_is_available_for_ride_type(ride->type, TRACK_LIFT_HILL)) + { window_ride_operating_widgets[WIDX_LIFT_HILL_SPEED_LABEL].type = WWT_LABEL; window_ride_operating_widgets[WIDX_LIFT_HILL_SPEED].type = WWT_SPINNER; window_ride_operating_widgets[WIDX_LIFT_HILL_SPEED_INCREASE].type = WWT_BUTTON; diff --git a/src/openrct2/ride/RideGroupManager.cpp b/src/openrct2/ride/RideGroupManager.cpp index 99eac84177..ac282d41c8 100644 --- a/src/openrct2/ride/RideGroupManager.cpp +++ b/src/openrct2/ride/RideGroupManager.cpp @@ -108,7 +108,7 @@ const RideGroup * RideGroupManager::GetRideGroup(const uint8 rideType, const rct switch (rideType) { case RIDE_TYPE_CORKSCREW_ROLLER_COASTER: - if (rideEntry->enabledTrackPieces & (1ULL << TRACK_VERTICAL_LOOP)) + if (ride_entry_get_supported_track_pieces(rideEntry) & (1ULL << TRACK_VERTICAL_LOOP)) return &ride_group_corkscrew_rc; else return &ride_group_hypercoaster; @@ -118,17 +118,17 @@ const RideGroup * RideGroupManager::GetRideGroup(const uint8 rideType, const rct else return &ride_group_junior_rc; case RIDE_TYPE_CAR_RIDE: - if (rideEntry->enabledTrackPieces & (1ULL << TRACK_SLOPE_STEEP)) + if (ride_entry_get_supported_track_pieces(rideEntry) & (1ULL << TRACK_SLOPE_STEEP)) return &ride_group_monster_trucks; else return &ride_group_car_ride; case RIDE_TYPE_TWISTER_ROLLER_COASTER: - if (rideEntry->enabledTrackPieces & (1ULL << TRACK_VERTICAL_LOOP)) + if (!(rideEntry->flags & RIDE_ENTRY_FLAG_NO_INVERSIONS)) return &ride_group_steel_twister_rc; else return &ride_group_hyper_twister; case RIDE_TYPE_STEEL_WILD_MOUSE: - if (rideEntry->enabledTrackPieces & (1ULL << TRACK_SLOPE_STEEP)) + if (ride_entry_get_supported_track_pieces(rideEntry) & (1ULL << TRACK_SLOPE_STEEP)) return &ride_group_steel_wild_mouse; else return &ride_group_spinning_wild_mouse; diff --git a/src/openrct2/ride/Track.cpp b/src/openrct2/ride/Track.cpp index a27ba9f964..2cf90bc0e8 100644 --- a/src/openrct2/ride/Track.cpp +++ b/src/openrct2/ride/Track.cpp @@ -1004,7 +1004,6 @@ static money32 track_place(sint32 rideIndex, direction &= 3; gTrackGroundFlags = 0; - uint64 enabledTrackPieces = rideEntry->enabledTrackPieces & RideTypePossibleTrackConfigurations[ride->type]; uint32 rideTypeFlags = RideProperties[ride->type].flags; if ((ride->lifecycle_flags & RIDE_LIFECYCLE_INDESTRUCTIBLE_TRACK) && type == TRACK_ELEM_END_STATION) @@ -1047,7 +1046,7 @@ static money32 track_place(sint32 rideIndex, } // Backwards steep lift hills are allowed, even on roller coasters that do not support forwards steep lift hills. if ((liftHillAndAlternativeState & CONSTRUCTION_LIFT_HILL_SELECTED) && - !(enabledTrackPieces & (1ULL << TRACK_LIFT_HILL_STEEP)) && + !(RideTypePossibleTrackConfigurations[ride->type] & (1ULL << TRACK_LIFT_HILL_STEEP)) && !gCheatsEnableChainLiftOnAllTrack) { if (TrackFlags[type] & TRACK_ELEM_FLAG_IS_STEEP_UP) From c4d59201409a59f5c8e4d9b0f1d411591bfcab50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Janiszewski?= Date: Tue, 27 Mar 2018 20:43:20 +0200 Subject: [PATCH 70/93] Fix catching of polymorphic exception --- src/openrct2/object/ObjectFactory.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/openrct2/object/ObjectFactory.cpp b/src/openrct2/object/ObjectFactory.cpp index 6d4ee6ad2c..2956864330 100644 --- a/src/openrct2/object/ObjectFactory.cpp +++ b/src/openrct2/object/ObjectFactory.cpp @@ -259,9 +259,9 @@ namespace ObjectFactory } json_decref(jRoot); } - catch (std::runtime_error) + catch (const std::runtime_error &err) { - Console::Error::WriteLine("Unable to open or read '%s'", path.c_str()); + Console::Error::WriteLine("Unable to open or read '%s': %s", path.c_str(), err.what()); delete result; result = nullptr; From fa11f05dba959af757a36ac72045c90d94ae1bdb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Janiszewski?= Date: Tue, 27 Mar 2018 20:45:40 +0200 Subject: [PATCH 71/93] Remove unused variable --- src/openrct2-ui/windows/Ride.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/openrct2-ui/windows/Ride.cpp b/src/openrct2-ui/windows/Ride.cpp index 87da3fdba2..0aae7da632 100644 --- a/src/openrct2-ui/windows/Ride.cpp +++ b/src/openrct2-ui/windows/Ride.cpp @@ -3370,7 +3370,6 @@ static void window_ride_operating_invalidate(rct_window *w) { rct_widget *widgets; Ride *ride; - rct_ride_entry *rideEntry; rct_string_id format, caption, tooltip; widgets = window_ride_page_widgets[w->page]; @@ -3382,7 +3381,6 @@ static void window_ride_operating_invalidate(rct_window *w) window_ride_set_pressed_tab(w); ride = get_ride(w->number); - rideEntry = get_ride_entry_by_ride(ride); set_format_arg(0, rct_string_id, ride->name); set_format_arg(2, uint32, ride->name_arguments); From 808296e91f86fa9aa885534fdcf475eb5113d427 Mon Sep 17 00:00:00 2001 From: Ted John Date: Tue, 27 Mar 2018 21:55:38 +0100 Subject: [PATCH 72/93] Change json shop names to OpenRCT2 names --- src/openrct2/object/RideObject.cpp | 102 ++++++++++++++++------------- 1 file changed, 56 insertions(+), 46 deletions(-) diff --git a/src/openrct2/object/RideObject.cpp b/src/openrct2/object/RideObject.cpp index e253ecebf6..1e6a4c9e38 100644 --- a/src/openrct2/object/RideObject.cpp +++ b/src/openrct2/object/RideObject.cpp @@ -579,13 +579,26 @@ void RideObject::ReadJson(IReadObjectContext * context, const json_t * root) // Shop item auto rideSells = ObjectJsonHelpers::GetJsonStringArray(json_object_get(json_object_get(root, "properties"), "sells")); - if (rideSells.size() >= 1) + for (size_t i = 0; i < rideSells.size(); i++) { - _legacyType.shop_item = ParseShopItem(rideSells[0]); - } - if (rideSells.size() >= 2) - { - _legacyType.shop_item_secondary = ParseShopItem(rideSells[1]); + auto shopItem = ParseShopItem(rideSells[i]); + if (shopItem == SHOP_ITEM_NONE) + { + context->LogWarning(OBJECT_ERROR_INVALID_PROPERTY, "Unknown shop item"); + } + + if (i == 0) + { + _legacyType.shop_item = ParseShopItem(rideSells[0]); + } + else if (i == 1) + { + _legacyType.shop_item_secondary = ParseShopItem(rideSells[1]); + } + else + { + // More than 2 shop items not supported yet! + } } } else @@ -1036,9 +1049,6 @@ uint8 RideObject::ParseRideType(const std::string &s) { "mini_rc", RIDE_TYPE_MINI_ROLLER_COASTER }, { "mine_ride", RIDE_TYPE_MINE_RIDE }, { "lim_launched_rc", RIDE_TYPE_LIM_LAUNCHED_ROLLER_COASTER }, - - // TEMPORARY: - { "restroom", RIDE_TYPE_TOILETS }, }; auto result = LookupTable.find(s); return (result != LookupTable.end()) ? @@ -1067,43 +1077,43 @@ uint8 RideObject::ParseShopItem(const std::string &s) { static const std::unordered_map LookupTable { - { "burger", SHOP_ITEM_BURGER }, - { "fries", SHOP_ITEM_CHIPS }, - { "icecream", SHOP_ITEM_ICE_CREAM }, - { "cottoncandy", SHOP_ITEM_CANDYFLOSS }, - { "pizza", SHOP_ITEM_PIZZA }, - { "popcorn", SHOP_ITEM_POPCORN }, - { "hotdog", SHOP_ITEM_HOT_DOG }, - { "seafood", SHOP_ITEM_TENTACLE }, - { "candyapple", SHOP_ITEM_TOFFEE_APPLE }, - { "donut", SHOP_ITEM_DOUGHNUT }, - { "chicken", SHOP_ITEM_CHICKEN }, - { "pretzel", SHOP_ITEM_PRETZEL }, - { "funnelcake", SHOP_ITEM_FUNNEL_CAKE }, - { "beefnoodles", SHOP_ITEM_BEEF_NOODLES }, - { "friednoodles", SHOP_ITEM_FRIED_RICE_NOODLES }, - { "wontonsoup", SHOP_ITEM_WONTON_SOUP }, - { "meatballsoup", SHOP_ITEM_MEATBALL_SOUP }, - { "subsandwich", SHOP_ITEM_SUB_SANDWICH }, - { "cookies", SHOP_ITEM_COOKIE }, - { "roastsausage", SHOP_ITEM_ROAST_SAUSAGE }, - { "cola", SHOP_ITEM_DRINK }, - { "coffee", SHOP_ITEM_COFFEE }, - { "lemonade", SHOP_ITEM_LEMONADE }, - { "hotchocolate", SHOP_ITEM_CHOCOLATE }, - { "icedtea", SHOP_ITEM_ICED_TEA }, - { "fruitjuice", SHOP_ITEM_FRUIT_JUICE }, - { "soybeanmilk", SHOP_ITEM_SOYBEAN_MILK }, - { "sujongkwa", SHOP_ITEM_SU_JONGKWA }, - { "balloon", SHOP_ITEM_BALLOON }, - { "plushtoy", SHOP_ITEM_TOY }, - { "map", SHOP_ITEM_MAP }, - { "onridephoto", SHOP_ITEM_PHOTO }, - { "umbrella", SHOP_ITEM_UMBRELLA }, - { "voucher", SHOP_ITEM_VOUCHER }, - { "hat", SHOP_ITEM_HAT }, - { "tshirt", SHOP_ITEM_TSHIRT }, - { "sunglasses", SHOP_ITEM_SUNGLASSES }, + { "burger", SHOP_ITEM_BURGER }, + { "chips", SHOP_ITEM_CHIPS }, + { "ice_cream", SHOP_ITEM_ICE_CREAM }, + { "candyfloss", SHOP_ITEM_CANDYFLOSS }, + { "pizza", SHOP_ITEM_PIZZA }, + { "popcorn", SHOP_ITEM_POPCORN }, + { "hot_dog", SHOP_ITEM_HOT_DOG }, + { "tentacle", SHOP_ITEM_TENTACLE }, + { "toffee_apple", SHOP_ITEM_TOFFEE_APPLE }, + { "doughnut", SHOP_ITEM_DOUGHNUT }, + { "chicken", SHOP_ITEM_CHICKEN }, + { "pretzel", SHOP_ITEM_PRETZEL }, + { "funnel_cake", SHOP_ITEM_FUNNEL_CAKE }, + { "beef_noodles", SHOP_ITEM_BEEF_NOODLES }, + { "fried_rice_noodles", SHOP_ITEM_FRIED_RICE_NOODLES }, + { "wonton_soup", SHOP_ITEM_WONTON_SOUP }, + { "meatball_soup", SHOP_ITEM_MEATBALL_SOUP }, + { "sub_sandwich", SHOP_ITEM_SUB_SANDWICH }, + { "cookies", SHOP_ITEM_COOKIE }, + { "roast_sausage", SHOP_ITEM_ROAST_SAUSAGE }, + { "drink", SHOP_ITEM_DRINK }, + { "coffee", SHOP_ITEM_COFFEE }, + { "lemonade", SHOP_ITEM_LEMONADE }, + { "chocolate", SHOP_ITEM_CHOCOLATE }, + { "iced_tea", SHOP_ITEM_ICED_TEA }, + { "fruit_juice", SHOP_ITEM_FRUIT_JUICE }, + { "soybean_milk", SHOP_ITEM_SOYBEAN_MILK }, + { "su_jongkwa", SHOP_ITEM_SU_JONGKWA }, + { "balloon", SHOP_ITEM_BALLOON }, + { "toy", SHOP_ITEM_TOY }, + { "map", SHOP_ITEM_MAP }, + { "photo", SHOP_ITEM_PHOTO }, + { "umbrella", SHOP_ITEM_UMBRELLA }, + { "voucher", SHOP_ITEM_VOUCHER }, + { "hat", SHOP_ITEM_HAT }, + { "tshirt", SHOP_ITEM_TSHIRT }, + { "sunglasses", SHOP_ITEM_SUNGLASSES }, }; auto result = LookupTable.find(s); return (result != LookupTable.end()) ? From 0c03fe4dc5ed1cd047e270f195a29076ad3fd0a0 Mon Sep 17 00:00:00 2001 From: Ted John Date: Tue, 27 Mar 2018 22:06:16 +0100 Subject: [PATCH 73/93] Update objects to v1.0-beta.4 --- CMakeLists.txt | 4 ++-- openrct2.proj | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index aeeef42c2f..4d6bc42e9a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,8 +16,8 @@ set(CMAKE_MACOSX_RPATH 1) set(TITLE_SEQUENCE_URL "https://github.com/OpenRCT2/title-sequences/releases/download/v0.1.2/title-sequence-v0.1.2.zip") set(TITLE_SEQUENCE_SHA1 "1136ef92bfb05cd1cba9831ba6dc4a653d87a246") -set(OBJECTS_URL "https://github.com/OpenRCT2/objects/releases/download/v1.0-beta.3/objects.zip") -set(OBJECTS_SHA1 "0cffb52762336036a2366a5c733776a7aeead6bb") +set(OBJECTS_URL "https://github.com/OpenRCT2/objects/releases/download/v1.0-beta.4/objects.zip") +set(OBJECTS_SHA1 "10c32779b1bd78e97b90fc8cac11950a3abf982b") option(FORCE32 "Force 32-bit build. It will add `-m32` to compiler flags.") option(WITH_TESTS "Build tests") diff --git a/openrct2.proj b/openrct2.proj index 99d776b74e..9a4ca2314e 100644 --- a/openrct2.proj +++ b/openrct2.proj @@ -71,8 +71,8 @@ 667f873ab7a4d246062565fad32fb6d8e203ee73 https://github.com/OpenRCT2/title-sequences/releases/download/v0.1.2/title-sequence-v0.1.2.zip 1136ef92bfb05cd1cba9831ba6dc4a653d87a246 - https://github.com/OpenRCT2/objects/releases/download/v1.0-beta.3/objects.zip - 0cffb52762336036a2366a5c733776a7aeead6bb + https://github.com/OpenRCT2/objects/releases/download/v1.0-beta.4/objects.zip + 10c32779b1bd78e97b90fc8cac11950a3abf982b From ce06550b8f4f1dac498b98676c96f807194acdef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Janiszewski?= Date: Tue, 27 Mar 2018 23:17:35 +0200 Subject: [PATCH 74/93] Fix mismatched deleter in ~ImageTable() --- src/openrct2/object/ImageTable.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/openrct2/object/ImageTable.cpp b/src/openrct2/object/ImageTable.cpp index 7111113971..29236b6811 100644 --- a/src/openrct2/object/ImageTable.cpp +++ b/src/openrct2/object/ImageTable.cpp @@ -28,7 +28,7 @@ ImageTable::~ImageTable() { for (auto &entry : _entries) { - delete entry.offset; + delete [] entry.offset; } } } From 617c14b8687b8fbd732cb2d1ac18a2844d080bf5 Mon Sep 17 00:00:00 2001 From: Ted John Date: Tue, 27 Mar 2018 22:36:31 +0100 Subject: [PATCH 75/93] Do not overwrite car.flags --- src/openrct2/object/RideObject.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/openrct2/object/RideObject.cpp b/src/openrct2/object/RideObject.cpp index 1e6a4c9e38..68c3cb7875 100644 --- a/src/openrct2/object/RideObject.cpp +++ b/src/openrct2/object/RideObject.cpp @@ -844,7 +844,7 @@ rct_ride_entry_vehicle RideObject::ReadJsonCar(const json_t * jCar) { "curvedLiftHill", VEHICLE_SPRITE_FLAG_CURVED_LIFT_HILL }, { "VEHICLE_SPRITE_FLAG_15", VEHICLE_SPRITE_FLAG_15 } }); - car.flags = ObjectJsonHelpers::GetFlags(jCar, { + car.flags |= ObjectJsonHelpers::GetFlags(jCar, { { "VEHICLE_ENTRY_FLAG_POWERED_RIDE_UNRESTRICTED_GRAVITY", VEHICLE_ENTRY_FLAG_POWERED_RIDE_UNRESTRICTED_GRAVITY }, { "VEHICLE_ENTRY_FLAG_NO_UPSTOP_WHEELS", VEHICLE_ENTRY_FLAG_NO_UPSTOP_WHEELS }, { "VEHICLE_ENTRY_FLAG_NO_UPSTOP_BOBSLEIGH", VEHICLE_ENTRY_FLAG_NO_UPSTOP_BOBSLEIGH }, From 28067c0bad30e78cfabffdf814287376bc5feea9 Mon Sep 17 00:00:00 2001 From: Michael Steenbeek Date: Wed, 28 Mar 2018 09:42:15 +0200 Subject: [PATCH 76/93] Add JSON object download to Xcode project --- OpenRCT2.xcodeproj/project.pbxproj | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/OpenRCT2.xcodeproj/project.pbxproj b/OpenRCT2.xcodeproj/project.pbxproj index 8277955949..3f362e31f2 100644 --- a/OpenRCT2.xcodeproj/project.pbxproj +++ b/OpenRCT2.xcodeproj/project.pbxproj @@ -21,12 +21,13 @@ /* End PBXAggregateTarget section */ /* Begin PBXBuildFile section */ + 4C1A53ED205FD1A0000F8EF5 /* SceneryObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C1A53EC205FD19F000F8EF5 /* SceneryObject.cpp */; }; 4C3B4236205914F7000C5BB7 /* InGameConsole.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C3B4234205914F7000C5BB7 /* InGameConsole.cpp */; }; 4C3B423820591513000C5BB7 /* StdInOutConsole.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C3B423720591513000C5BB7 /* StdInOutConsole.cpp */; }; - 4C1A53ED205FD1A0000F8EF5 /* SceneryObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C1A53EC205FD19F000F8EF5 /* SceneryObject.cpp */; }; 4C93F1AD1F8CD9F000A9330D /* Input.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C93F1AC1F8CD9F000A9330D /* Input.cpp */; }; 4C93F1AF1F8CD9F600A9330D /* KeyboardShortcut.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C93F1AE1F8CD9F600A9330D /* KeyboardShortcut.cpp */; }; 4CE9AAAD1FDA7B14004093C6 /* ObjectJsonHelpers.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CE9AAAB1FDA7B14004093C6 /* ObjectJsonHelpers.cpp */; }; + 4CF67197206B7E720034ADDD /* object in Resources */ = {isa = PBXBuildFile; fileRef = 4CF67196206B7E720034ADDD /* object */; }; C61ADB1F1FB6A0A70024F2EF /* TopToolbar.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C61ADB1E1FB6A0A60024F2EF /* TopToolbar.cpp */; }; C61ADB211FB7DC060024F2EF /* Scenery.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C61ADB201FB7DC060024F2EF /* Scenery.cpp */; }; C61ADB231FBBCB8B0024F2EF /* GameBottomToolbar.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C61ADB221FBBCB8A0024F2EF /* GameBottomToolbar.cpp */; }; @@ -588,10 +589,10 @@ /* Begin PBXFileReference section */ 4C04D69F2056AA9600F82EBA /* linenoise.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = linenoise.hpp; sourceTree = ""; }; + 4C1A53EC205FD19F000F8EF5 /* SceneryObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SceneryObject.cpp; sourceTree = ""; }; 4C3B4234205914F7000C5BB7 /* InGameConsole.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InGameConsole.cpp; sourceTree = ""; }; 4C3B4235205914F7000C5BB7 /* InGameConsole.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InGameConsole.h; sourceTree = ""; }; 4C3B423720591513000C5BB7 /* StdInOutConsole.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StdInOutConsole.cpp; sourceTree = ""; }; - 4C1A53EC205FD19F000F8EF5 /* SceneryObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SceneryObject.cpp; sourceTree = ""; }; 4C4C1E971F58226500560300 /* TrackDesign.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TrackDesign.cpp; sourceTree = ""; }; 4C4C1E991F5832AA00560300 /* TrackDesign.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TrackDesign.h; sourceTree = ""; }; 4C5DFF401FAC69D200CB093A /* Date.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Date.cpp; sourceTree = ""; }; @@ -852,6 +853,7 @@ 4CE462491FD1613D0001CD98 /* Platform.Win32.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Platform.Win32.cpp; sourceTree = ""; }; 4CE9AAAB1FDA7B14004093C6 /* ObjectJsonHelpers.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ObjectJsonHelpers.cpp; sourceTree = ""; }; 4CE9AAAC1FDA7B14004093C6 /* ObjectJsonHelpers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ObjectJsonHelpers.h; sourceTree = ""; }; + 4CF67196206B7E720034ADDD /* object */ = {isa = PBXFileReference; lastKnownFileType = folder; name = object; path = data/object; sourceTree = ""; }; 4CFE4E7B1F90A3F1005243C2 /* Peep.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Peep.cpp; sourceTree = ""; }; 4CFE4E7C1F90A3F1005243C2 /* Peep.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Peep.h; sourceTree = ""; }; 4CFE4E7D1F90A3F1005243C2 /* PeepData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PeepData.cpp; sourceTree = ""; }; @@ -1681,6 +1683,7 @@ D497D06F1C20FD52002BF46A = { isa = PBXGroup; children = ( + 4CF67196206B7E720034ADDD /* object */, D41B72431C21015A0080A7B9 /* Sources */, D497D07A1C20FD52002BF46A /* Resources */, D41B73ED1C21017D0080A7B9 /* Libraries */, @@ -2725,6 +2728,7 @@ isa = PBXNativeTarget; buildConfigurationList = D497D0891C20FD53002BF46A /* Build configuration list for PBXNativeTarget "OpenRCT2" */; buildPhases = ( + 4CF67195206B7BEF0034ADDD /* Download JSON objects */, D4E09E831E049C0600F53CE3 /* Download Title Sequences */, D4EC012A1C25532B00DAFE69 /* Setup AppIcon */, D4CA88671D4E962100060C11 /* Get Git Variables */, @@ -2836,6 +2840,7 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + 4CF67197206B7E720034ADDD /* object in Resources */, D41B74731C2125E50080A7B9 /* Assets.xcassets in Resources */, D4EC48E61C2637710024B507 /* g2.dat in Resources */, D4EC48E71C2637710024B507 /* language in Resources */, @@ -2855,6 +2860,20 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ + 4CF67195206B7BEF0034ADDD /* Download JSON objects */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Download JSON objects"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "version=\"1.0-beta.4\"\nzipname=\"objects.zip\"\nliburl=\"https://github.com/OpenRCT2/objects/releases/download/v$version/$zipname\"\n\n[[ ! -d \"${SRCROOT}/data/object\" || ! -e \"${SRCROOT}/objectsversion\" || $(head -n 1 \"${SRCROOT}/objectsversion\") != $version ]]\noutdated=$?\n\nif [[ $outdated -eq 0 ]]; then\nif [[ -d \"${SRCROOT}/data/object\" ]]; then rm -r \"${SRCROOT}/data/object\"; fi\nmkdir -p \"${SRCROOT}/data/object\"\n\ncurl -L -o \"${SRCROOT}/data/object/$zipname\" \"$liburl\"\nunzip -uaq -d \"${SRCROOT}/data/object\" \"${SRCROOT}/data/object/$zipname\"\nrm \"${SRCROOT}/data/object/$zipname\"\n\necho $version > \"${SRCROOT}/objectsversion\"\nfi"; + }; C68B2D471EC790710020651C /* Download Libraries */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; From b8ae3f5e91b9af599f88d2f2b84ee1ce90b9ab4c Mon Sep 17 00:00:00 2001 From: Ted John Date: Wed, 28 Mar 2018 21:13:59 +0100 Subject: [PATCH 77/93] Fix cookie json item name --- src/openrct2/object/RideObject.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/openrct2/object/RideObject.cpp b/src/openrct2/object/RideObject.cpp index 68c3cb7875..604eae4a0d 100644 --- a/src/openrct2/object/RideObject.cpp +++ b/src/openrct2/object/RideObject.cpp @@ -1095,7 +1095,7 @@ uint8 RideObject::ParseShopItem(const std::string &s) { "wonton_soup", SHOP_ITEM_WONTON_SOUP }, { "meatball_soup", SHOP_ITEM_MEATBALL_SOUP }, { "sub_sandwich", SHOP_ITEM_SUB_SANDWICH }, - { "cookies", SHOP_ITEM_COOKIE }, + { "cookie", SHOP_ITEM_COOKIE }, { "roast_sausage", SHOP_ITEM_ROAST_SAUSAGE }, { "drink", SHOP_ITEM_DRINK }, { "coffee", SHOP_ITEM_COFFEE }, From 5eeecd82bd67e66ca76fb0cb01602a957917588b Mon Sep 17 00:00:00 2001 From: Gymnasiast Date: Wed, 28 Mar 2018 22:41:39 +0200 Subject: [PATCH 78/93] Remove fixes to vanilla objects (moved to JSON) --- src/openrct2/object/RideObject.cpp | 50 ------------------------------ src/openrct2/object/RideObject.h | 1 - 2 files changed, 51 deletions(-) diff --git a/src/openrct2/object/RideObject.cpp b/src/openrct2/object/RideObject.cpp index 604eae4a0d..adec33615c 100644 --- a/src/openrct2/object/RideObject.cpp +++ b/src/openrct2/object/RideObject.cpp @@ -119,8 +119,6 @@ void RideObject::ReadLegacy(IReadObjectContext * context, IStream * stream) { context->LogError(OBJECT_ERROR_INVALID_PROPERTY, "Nausea multiplier too high."); } - - PerformFixes(); } void RideObject::Load() @@ -407,54 +405,6 @@ void RideObject::ReadLegacyVehicle(IReadObjectContext * context, IStream * strea stream->Seek(4, STREAM_SEEK_CURRENT); } -void RideObject::PerformFixes() -{ - std::string identifier = GetIdentifier(); - - // Add boosters if the track type is eligible - for (auto rideType : _legacyType.ride_type) - { - if (ride_type_supports_boosters(rideType)) - { - _legacyType.enabledTrackPieces |= (1ULL << TRACK_BOOSTER); - } - } - - // The rocket cars could take 3 cars per train in RCT1. Restore this. - if (String::Equals(identifier, "RCKC ")) - { - _legacyType.max_cars_in_train = 3 + _legacyType.zero_cars; - } - // The Wooden Roller Coaster could take 7 cars per train in RCT1. - else if (String::Equals(identifier, "PTCT1 ")) - { - _legacyType.max_cars_in_train = 7 + _legacyType.zero_cars; - } - // The Looping Roller Coaster could take 8 cars per train in RCT1. - else if (String::Equals(identifier, "SCHT1 ")) - { - _legacyType.max_cars_in_train = 8 + _legacyType.zero_cars; - } - // The Steel Twister could take 8 cars per train in RCT1. (The other two vehicles are already correct.) - else if (String::Equals(identifier, "BMSD ") || String::Equals(identifier, "BMSU ")) - { - _legacyType.max_cars_in_train = 8 + _legacyType.zero_cars; - } - // Wacky Worlds' Crocodile Ride (a log flume vehicle) is incorrectly locked to 5 cars. - else if (String::Equals(identifier, "CROCFLUM")) - { - _legacyType.cars_per_flat_ride = 0xFF; - } - // All vanilla/WW/OCC Junior RC vehicles incorrectly have this flag set - else if (String::Equals(identifier, "ZLDB ") || - String::Equals(identifier, "ZLOG ") || - String::Equals(identifier, "ZPANDA ") || - String::Equals(identifier, "WHICGRUB")) - { - _legacyType.enabledTrackPieces &= ~(1ULL << TRACK_SLOPE_STEEP); - } -} - uint8 RideObject::CalculateNumVerticalFrames(const rct_ride_entry_vehicle * vehicleEntry) { // 0x6DE90B diff --git a/src/openrct2/object/RideObject.h b/src/openrct2/object/RideObject.h index 0e90c6d2ec..35bb401c58 100644 --- a/src/openrct2/object/RideObject.h +++ b/src/openrct2/object/RideObject.h @@ -46,7 +46,6 @@ public: private: void ReadLegacyVehicle(IReadObjectContext * context, IStream * stream, rct_ride_entry_vehicle * vehicle); - void PerformFixes(); void ReadJsonVehicleInfo(IReadObjectContext * context, const json_t * properties); std::vector ReadJsonCars(const json_t * jCars); From 742edd45da1e2423c8a91cdeacc34922a3e9ec08 Mon Sep 17 00:00:00 2001 From: Ted John Date: Wed, 28 Mar 2018 22:14:25 +0100 Subject: [PATCH 79/93] Update loading object images to use inclusive ranges --- src/openrct2/object/ObjectJsonHelpers.cpp | 58 +++++++++++------------ 1 file changed, 28 insertions(+), 30 deletions(-) diff --git a/src/openrct2/object/ObjectJsonHelpers.cpp b/src/openrct2/object/ObjectJsonHelpers.cpp index 2324c75d8a..66af224fb6 100644 --- a/src/openrct2/object/ObjectJsonHelpers.cpp +++ b/src/openrct2/object/ObjectJsonHelpers.cpp @@ -233,7 +233,7 @@ namespace ObjectJsonHelpers return objectPath; } - static std::vector LoadObjectImages(IReadObjectContext * context, const std::string &name, uint32 start, uint32 end) + static std::vector LoadObjectImages(IReadObjectContext * context, const std::string &name, const std::vector &range) { std::vector result; auto objectPath = FindLegacyObject(name); @@ -241,35 +241,41 @@ namespace ObjectJsonHelpers if (obj != nullptr) { auto &imgTable = static_cast(obj)->GetImageTable(); - auto numImages = imgTable.GetCount(); + auto numImages = (sint32)imgTable.GetCount(); auto images = imgTable.GetImages(); - for (uint32 i = start; i < Math::Min(numImages, end); i++) + size_t placeHoldersAdded = 0; + for (auto i : range) { - auto &objg1 = images[i]; - auto length = g1_calculate_data_size(&objg1); - auto g1 = objg1; - g1.offset = (uint8 *)std::malloc(length); - std::memcpy(g1.offset, objg1.offset, length); - result.push_back(g1); + if (i >= 0 && i < numImages) + { + auto &objg1 = images[i]; + auto length = g1_calculate_data_size(&objg1); + auto g1 = objg1; + g1.offset = (uint8 *)std::malloc(length); + std::memcpy(g1.offset, objg1.offset, length); + result.push_back(g1); + } + else + { + auto g1 = rct_g1_element{}; + result.push_back(g1); + placeHoldersAdded++; + } } delete obj; + + // Log place holder information + if (placeHoldersAdded > 0) + { + std::string msg = "Adding " + std::to_string(placeHoldersAdded) + " placeholders"; + context->LogWarning(OBJECT_ERROR_INVALID_PROPERTY, msg.c_str()); + } } else { std::string msg = "Unable to open '" + objectPath + "'"; context->LogWarning(OBJECT_ERROR_INVALID_PROPERTY, msg.c_str()); - } - - // Add place holders - auto placeHolders = (size_t)(end - start) - result.size(); - if (placeHolders > 0) - { - if (obj != nullptr) - { - std::string msg = "Adding " + std::to_string(placeHolders) + " placeholders"; - context->LogWarning(OBJECT_ERROR_INVALID_PROPERTY, msg.c_str()); - } - for (size_t i = 0; i < placeHolders; i++) + for (size_t i = 0; i < range.size(); i++) { auto g1 = rct_g1_element{}; result.push_back(g1); @@ -309,21 +315,13 @@ namespace ObjectJsonHelpers { auto name = s.substr(14); auto rangeStart = name.find('['); - auto imgStart = 0; - auto imgEnd = INT16_MAX; if (rangeStart != std::string::npos) { auto rangeString = name.substr(rangeStart); auto range = ParseRange(name.substr(rangeStart)); name = name.substr(0, rangeStart); - - if (range.size() > 0) - { - imgStart = range.front(); - imgEnd = range.back(); - } + result = LoadObjectImages(context, name, range); } - return LoadObjectImages(context, name, imgStart, imgEnd); } return result; } From 0779859d2b2426db1b8fb69133feb51e37bfa8e7 Mon Sep 17 00:00:00 2001 From: Ted John Date: Wed, 28 Mar 2018 22:25:45 +0100 Subject: [PATCH 80/93] Do not download objects if they already exist --- CMakeLists.txt | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4d6bc42e9a..73ead59cd9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -214,10 +214,15 @@ if (DOWNLOAD_TITLE_SEQUENCES) endif ()") endif () if (DOWNLOAD_OBJECTS) - set(OBJECT_DIR "\$ENV{DESTDIR}${CMAKE_INSTALL_FULL_DATADIR}/${PROJECT}/object") - install(CODE "file(DOWNLOAD ${OBJECTS_URL} ${OBJECT_DIR}/objects.zip EXPECTED_HASH SHA1=${OBJECTS_SHA1} SHOW_PROGRESS)") - install(CODE "execute_process(COMMAND \"${CMAKE_COMMAND}\" -E chdir ${OBJECT_DIR}/ \"${CMAKE_COMMAND}\" -E tar xvf objects.zip)") - install(CODE "file(REMOVE ${OBJECT_DIR}/objects.zip)") + # If rct2.wtrcyan.json or data/object/ exists, assume all the objects are already present + install(CODE + "if (EXISTS \"\$ENV{DESTDIR}/${CMAKE_INSTALL_FULL_DATADIR}/${PROJECT}/object/rct2/water/rct2.wtrcyan.json\" OR EXISTS ${CMAKE_SOURCE_DIR}/data/object/)\n\ + message(\"Using cached objects\")\n\ + else () \n\ + file(DOWNLOAD ${OBJECTS_URL} \$ENV{DESTDIR}/${CMAKE_INSTALL_FULL_DATADIR}/${PROJECT}/object/objects.zip EXPECTED_HASH SHA1=${OBJECTS_SHA1} SHOW_PROGRESS)\n\ + execute_process(COMMAND \"${CMAKE_COMMAND}\" -E chdir \$ENV{DESTDIR}/${CMAKE_INSTALL_FULL_DATADIR}/${PROJECT}/object/ \"${CMAKE_COMMAND}\" -E tar xvf objects.zip)\n\ + file(REMOVE \$ENV{DESTDIR}/${CMAKE_INSTALL_FULL_DATADIR}/${PROJECT}/object/objects.zip)\n\ + endif ()") endif () install(TARGETS "libopenrct2" LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}") From dcc834ae0ad634fb0180c0efda4372488df43b2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Janiszewski?= Date: Wed, 28 Mar 2018 23:45:48 +0200 Subject: [PATCH 81/93] Mark ObjectJsonHelpers::GetFlags as static --- src/openrct2/object/ObjectJsonHelpers.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/openrct2/object/ObjectJsonHelpers.h b/src/openrct2/object/ObjectJsonHelpers.h index 8daa454f82..5f56a523bb 100644 --- a/src/openrct2/object/ObjectJsonHelpers.h +++ b/src/openrct2/object/ObjectJsonHelpers.h @@ -1,4 +1,4 @@ -#pragma region Copyright (c) 2014-2017 OpenRCT2 Developers +#pragma region Copyright (c) 2014-2018 OpenRCT2 Developers /***************************************************************************** * OpenRCT2, an open source clone of Roller Coaster Tycoon 2. * @@ -42,7 +42,7 @@ namespace ObjectJsonHelpers void LoadImages(IReadObjectContext * context, const json_t * root, ImageTable &imageTable); template - T GetFlags(const json_t * obj, std::initializer_list> list) + static T GetFlags(const json_t * obj, std::initializer_list> list) { T flags = 0; for (const auto &item : list) From b163064f6cd6f7a96e799ed60d9eafcc5e3c5996 Mon Sep 17 00:00:00 2001 From: Ted John Date: Wed, 28 Mar 2018 23:15:15 +0100 Subject: [PATCH 82/93] Update objects to v1.0 --- CMakeLists.txt | 4 ++-- OpenRCT2.xcodeproj/project.pbxproj | 2 +- openrct2.proj | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 73ead59cd9..17c75c8342 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,8 +16,8 @@ set(CMAKE_MACOSX_RPATH 1) set(TITLE_SEQUENCE_URL "https://github.com/OpenRCT2/title-sequences/releases/download/v0.1.2/title-sequence-v0.1.2.zip") set(TITLE_SEQUENCE_SHA1 "1136ef92bfb05cd1cba9831ba6dc4a653d87a246") -set(OBJECTS_URL "https://github.com/OpenRCT2/objects/releases/download/v1.0-beta.4/objects.zip") -set(OBJECTS_SHA1 "10c32779b1bd78e97b90fc8cac11950a3abf982b") +set(OBJECTS_URL "https://github.com/OpenRCT2/objects/releases/download/v1.0/objects.zip") +set(OBJECTS_SHA1 "5b9dc88b9f42a76d05d1584f10db845247a9b198") option(FORCE32 "Force 32-bit build. It will add `-m32` to compiler flags.") option(WITH_TESTS "Build tests") diff --git a/OpenRCT2.xcodeproj/project.pbxproj b/OpenRCT2.xcodeproj/project.pbxproj index 3f362e31f2..e75854dc5d 100644 --- a/OpenRCT2.xcodeproj/project.pbxproj +++ b/OpenRCT2.xcodeproj/project.pbxproj @@ -2872,7 +2872,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "version=\"1.0-beta.4\"\nzipname=\"objects.zip\"\nliburl=\"https://github.com/OpenRCT2/objects/releases/download/v$version/$zipname\"\n\n[[ ! -d \"${SRCROOT}/data/object\" || ! -e \"${SRCROOT}/objectsversion\" || $(head -n 1 \"${SRCROOT}/objectsversion\") != $version ]]\noutdated=$?\n\nif [[ $outdated -eq 0 ]]; then\nif [[ -d \"${SRCROOT}/data/object\" ]]; then rm -r \"${SRCROOT}/data/object\"; fi\nmkdir -p \"${SRCROOT}/data/object\"\n\ncurl -L -o \"${SRCROOT}/data/object/$zipname\" \"$liburl\"\nunzip -uaq -d \"${SRCROOT}/data/object\" \"${SRCROOT}/data/object/$zipname\"\nrm \"${SRCROOT}/data/object/$zipname\"\n\necho $version > \"${SRCROOT}/objectsversion\"\nfi"; + shellScript = "version=\"1.0\"\nzipname=\"objects.zip\"\nliburl=\"https://github.com/OpenRCT2/objects/releases/download/v$version/$zipname\"\n\n[[ ! -d \"${SRCROOT}/data/object\" || ! -e \"${SRCROOT}/objectsversion\" || $(head -n 1 \"${SRCROOT}/objectsversion\") != $version ]]\noutdated=$?\n\nif [[ $outdated -eq 0 ]]; then\nif [[ -d \"${SRCROOT}/data/object\" ]]; then rm -r \"${SRCROOT}/data/object\"; fi\nmkdir -p \"${SRCROOT}/data/object\"\n\ncurl -L -o \"${SRCROOT}/data/object/$zipname\" \"$liburl\"\nunzip -uaq -d \"${SRCROOT}/data/object\" \"${SRCROOT}/data/object/$zipname\"\nrm \"${SRCROOT}/data/object/$zipname\"\n\necho $version > \"${SRCROOT}/objectsversion\"\nfi"; }; C68B2D471EC790710020651C /* Download Libraries */ = { isa = PBXShellScriptBuildPhase; diff --git a/openrct2.proj b/openrct2.proj index 9a4ca2314e..49a9f6d1ec 100644 --- a/openrct2.proj +++ b/openrct2.proj @@ -71,8 +71,8 @@ 667f873ab7a4d246062565fad32fb6d8e203ee73 https://github.com/OpenRCT2/title-sequences/releases/download/v0.1.2/title-sequence-v0.1.2.zip 1136ef92bfb05cd1cba9831ba6dc4a653d87a246 - https://github.com/OpenRCT2/objects/releases/download/v1.0-beta.4/objects.zip - 10c32779b1bd78e97b90fc8cac11950a3abf982b + https://github.com/OpenRCT2/objects/releases/download/v1.0/objects.zip + 5b9dc88b9f42a76d05d1584f10db845247a9b198 From cfb5a6b39dbb6e6bca550fa7cfb0937c4f7274b2 Mon Sep 17 00:00:00 2001 From: Michael Steenbeek Date: Thu, 29 Mar 2018 13:00:01 +0200 Subject: [PATCH 83/93] Correct spelling of 'sujonkwa' --- data/language/en-GB.txt | 19 ++++++++++++------- src/openrct2/object/RideObject.cpp | 3 ++- src/openrct2/peep/Peep.cpp | 2 +- src/openrct2/ride/Ride.cpp | 4 ++-- src/openrct2/ride/Ride.h | 2 +- src/openrct2/ride/RideData.cpp | 6 +++--- src/openrct2/sprites.h | 2 +- 7 files changed, 22 insertions(+), 16 deletions(-) diff --git a/data/language/en-GB.txt b/data/language/en-GB.txt index 654f73626f..6b948877ee 100644 --- a/data/language/en-GB.txt +++ b/data/language/en-GB.txt @@ -1600,7 +1600,7 @@ STR_1594 :{SMALLFONT}{OPENQUOTES}This wonton soup from {STRINGID} is really g STR_1595 :{SMALLFONT}{OPENQUOTES}This meatball soup from {STRINGID} is really good value{ENDQUOTES} STR_1596 :{SMALLFONT}{OPENQUOTES}This fruit juice from {STRINGID} is really good value{ENDQUOTES} STR_1597 :{SMALLFONT}{OPENQUOTES}This soybean milk from {STRINGID} is really good value{ENDQUOTES} -STR_1598 :{SMALLFONT}{OPENQUOTES}This sujongkwa from {STRINGID} is really good value{ENDQUOTES} +STR_1598 :{SMALLFONT}{OPENQUOTES}This sujeonggwa from {STRINGID} is really good value{ENDQUOTES} STR_1599 :{SMALLFONT}{OPENQUOTES}This sub sandwich from {STRINGID} is really good value{ENDQUOTES} STR_1600 :{SMALLFONT}{OPENQUOTES}This cookie from {STRINGID} is really good value{ENDQUOTES} STR_1601 : @@ -1632,7 +1632,7 @@ STR_1626 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for wonton soup fro STR_1627 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for meatball soup from {STRINGID}{ENDQUOTES} STR_1628 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for fruit juice from {STRINGID}{ENDQUOTES} STR_1629 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for soybean milk from {STRINGID}{ENDQUOTES} -STR_1630 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for sujongkwa from {STRINGID}{ENDQUOTES} +STR_1630 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for sujeonggwa from {STRINGID}{ENDQUOTES} STR_1631 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for a sub sandwich from {STRINGID}{ENDQUOTES} STR_1632 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for a cookie from {STRINGID}{ENDQUOTES} STR_1633 : @@ -2118,7 +2118,7 @@ STR_2110 :{WINDOW_COLOUR_2}Wonton Soup price: STR_2111 :{WINDOW_COLOUR_2}Meatball Soup price: STR_2112 :{WINDOW_COLOUR_2}Fruit Juice price: STR_2113 :{WINDOW_COLOUR_2}Soybean Milk price: -STR_2114 :{WINDOW_COLOUR_2}Sujongkwa price: +STR_2114 :{WINDOW_COLOUR_2}Sujeonggwa price: STR_2115 :{WINDOW_COLOUR_2}Sub Sandwich price: STR_2116 :{WINDOW_COLOUR_2}Cookie price: STR_2117 :{WINDOW_COLOUR_2} @@ -2140,7 +2140,7 @@ STR_2132 :Wonton Soup STR_2133 :Meatball Soup STR_2134 :Fruit Juice STR_2135 :Soybean Milk -STR_2136 :Sujongkwa +STR_2136 :Sujeonggwa STR_2137 :Sub Sandwich STR_2138 :Cookie STR_2139 :Empty Bowl @@ -2162,7 +2162,7 @@ STR_2154 :Wonton Soups STR_2155 :Meatball Soups STR_2156 :Fruit Juices STR_2157 :Soybean Milks -STR_2158 :Sujongkwa +STR_2158 :Sujeonggwa STR_2159 :Sub Sandwiches STR_2160 :Cookies STR_2161 :Empty Bowls @@ -2184,7 +2184,7 @@ STR_2176 :some Wonton Soup STR_2177 :some Meatball Soup STR_2178 :a Fruit Juice STR_2179 :some Soybean Milk -STR_2180 :some Sujongkwa +STR_2180 :some Sujeonggwa STR_2181 :a Sub Sandwich STR_2182 :a Cookie STR_2183 :an Empty Bowl @@ -2206,7 +2206,7 @@ STR_2198 :Wonton Soup STR_2199 :Meatball Soup STR_2200 :Fruit Juice STR_2201 :Soybean Milk -STR_2202 :Sujongkwa +STR_2202 :Sujeonggwa STR_2203 :Sub Sandwich STR_2204 :Cookie STR_2205 :Empty Bowl @@ -5137,6 +5137,11 @@ STR_NAME :Six-seater Twister Trains [SUBMAR] STR_NAME :Submarines +# Spelling +[CINDR] +STR_NAME :Sujeonggwa Stall +STR_DESC :A stall selling Korean style Sujeonggwa drinks + #WW [CONDORRD] STR_NAME :Condor Trains diff --git a/src/openrct2/object/RideObject.cpp b/src/openrct2/object/RideObject.cpp index adec33615c..74754f69a7 100644 --- a/src/openrct2/object/RideObject.cpp +++ b/src/openrct2/object/RideObject.cpp @@ -1054,7 +1054,8 @@ uint8 RideObject::ParseShopItem(const std::string &s) { "iced_tea", SHOP_ITEM_ICED_TEA }, { "fruit_juice", SHOP_ITEM_FRUIT_JUICE }, { "soybean_milk", SHOP_ITEM_SOYBEAN_MILK }, - { "su_jongkwa", SHOP_ITEM_SU_JONGKWA }, + { "su_jongkwa", SHOP_ITEM_SUJEONGGWA }, + { "sujeonggwa", SHOP_ITEM_SUJEONGGWA }, { "balloon", SHOP_ITEM_BALLOON }, { "toy", SHOP_ITEM_TOY }, { "map", SHOP_ITEM_MAP }, diff --git a/src/openrct2/peep/Peep.cpp b/src/openrct2/peep/Peep.cpp index 6a207abfe9..69ffcf3c0b 100644 --- a/src/openrct2/peep/Peep.cpp +++ b/src/openrct2/peep/Peep.cpp @@ -850,7 +850,7 @@ static constexpr const uint8 byte_9822F4[] = { 110, // SHOP_ITEM_MEATBALL_SOUP 110, // SHOP_ITEM_FRUIT_JUICE 90, // SHOP_ITEM_SOYBEAN_MILK - 100, // SHOP_ITEM_SU_JONGKWA + 100, // SHOP_ITEM_SUJEONGGWA 130, // SHOP_ITEM_SUB_SANDWICH 75, // SHOP_ITEM_COOKIE 0, // SHOP_ITEM_EMPTY_BOWL_RED diff --git a/src/openrct2/ride/Ride.cpp b/src/openrct2/ride/Ride.cpp index c8314f89b3..4bae2ed945 100644 --- a/src/openrct2/ride/Ride.cpp +++ b/src/openrct2/ride/Ride.cpp @@ -7709,7 +7709,7 @@ bool shop_item_is_food_or_drink(sint32 shopItem) case SHOP_ITEM_MEATBALL_SOUP: case SHOP_ITEM_FRUIT_JUICE: case SHOP_ITEM_SOYBEAN_MILK: - case SHOP_ITEM_SU_JONGKWA: + case SHOP_ITEM_SUJEONGGWA: case SHOP_ITEM_SUB_SANDWICH: case SHOP_ITEM_COOKIE: case SHOP_ITEM_ROAST_SAUSAGE: @@ -7758,7 +7758,7 @@ bool shop_item_is_drink(sint32 shopItem) case SHOP_ITEM_ICED_TEA: case SHOP_ITEM_FRUIT_JUICE: case SHOP_ITEM_SOYBEAN_MILK: - case SHOP_ITEM_SU_JONGKWA: + case SHOP_ITEM_SUJEONGGWA: return true; default: return false; diff --git a/src/openrct2/ride/Ride.h b/src/openrct2/ride/Ride.h index a112fd6cf6..c8da9c85f0 100644 --- a/src/openrct2/ride/Ride.h +++ b/src/openrct2/ride/Ride.h @@ -857,7 +857,7 @@ enum { SHOP_ITEM_MEATBALL_SOUP, SHOP_ITEM_FRUIT_JUICE, SHOP_ITEM_SOYBEAN_MILK, - SHOP_ITEM_SU_JONGKWA, + SHOP_ITEM_SUJEONGGWA, SHOP_ITEM_SUB_SANDWICH, SHOP_ITEM_COOKIE, SHOP_ITEM_EMPTY_BOWL_RED, diff --git a/src/openrct2/ride/RideData.cpp b/src/openrct2/ride/RideData.cpp index ae67d56a62..5625ffb4da 100644 --- a/src/openrct2/ride/RideData.cpp +++ b/src/openrct2/ride/RideData.cpp @@ -1460,7 +1460,7 @@ const money8 DefaultShopItemPrice[SHOP_ITEM_COUNT] = { MONEY(1,50), // SHOP_ITEM_MEATBALL_SOUP MONEY(1,20), // SHOP_ITEM_FRUIT_JUICE MONEY(1,20), // SHOP_ITEM_SOYBEAN_MILK - MONEY(1,20), // SHOP_ITEM_SU_JONGKWA + MONEY(1,20), // SHOP_ITEM_SUJEONGGWA MONEY(1,50), // SHOP_ITEM_SUB_SANDWICH MONEY(0,70), // SHOP_ITEM_COOKIE MONEY(0,00), // SHOP_ITEM_EMPTY_BOWL_RED @@ -1576,7 +1576,7 @@ const uint32 ShopItemImage[SHOP_ITEM_COUNT] = { SPR_SHOP_ITEM_MEATBALL_SOUP, SPR_SHOP_ITEM_FRUIT_JUICE, SPR_SHOP_ITEM_SOYBEAN_MILK, - SPR_SHOP_ITEM_SU_JONGKWA, + SPR_SHOP_ITEM_SUJEONGGWA, SPR_SHOP_ITEM_SUB_SANDWICH, SPR_SHOP_ITEM_COOKIE, SPR_SHOP_ITEM_EMPTY_BOWL_RED, @@ -2482,7 +2482,7 @@ const rct_shop_item_stats ShopItemStats[SHOP_ITEM_COUNT] = { { 5, 14, 14, 16 }, // SHOP_ITEM_MEATBALL_SOUP { 4, 11, 19, 11 }, // SHOP_ITEM_FRUIT_JUICE { 4, 10, 14, 10 }, // SHOP_ITEM_SOYBEAN_MILK - { 3, 11, 14, 11 }, // SHOP_ITEM_SU_JONGKWA + { 3, 11, 14, 11 }, // SHOP_ITEM_SUJEONGGWA { 5, 19, 19, 17 }, // SHOP_ITEM_SUB_SANDWICH { 4, 8, 8, 8 }, // SHOP_ITEM_COOKIE { 0, 0, 0, 0 }, // SHOP_ITEM_EMPTY_BOWL_RED diff --git a/src/openrct2/sprites.h b/src/openrct2/sprites.h index f681a87f4e..b843134406 100644 --- a/src/openrct2/sprites.h +++ b/src/openrct2/sprites.h @@ -101,7 +101,7 @@ enum { SPR_SHOP_ITEM_MEATBALL_SOUP = 5100, SPR_SHOP_ITEM_FRUIT_JUICE = 5101, SPR_SHOP_ITEM_SOYBEAN_MILK = 5102, - SPR_SHOP_ITEM_SU_JONGKWA = 5103, + SPR_SHOP_ITEM_SUJEONGGWA = 5103, SPR_SHOP_ITEM_SUB_SANDWICH = 5104, SPR_SHOP_ITEM_COOKIE = 5105, SPR_SHOP_ITEM_EMPTY_BOWL_RED = 5106, From 68545e22da319c2eb51f4510082a2be01a00b6dd Mon Sep 17 00:00:00 2001 From: Michael Steenbeek Date: Thu, 29 Mar 2018 13:11:20 +0200 Subject: [PATCH 84/93] Remove en-GB overrides for vanilla objects --- data/language/en-GB.txt | 406 ---------------------------------------- 1 file changed, 406 deletions(-) diff --git a/data/language/en-GB.txt b/data/language/en-GB.txt index 6b948877ee..ec95413b66 100644 --- a/data/language/en-GB.txt +++ b/data/language/en-GB.txt @@ -4984,416 +4984,10 @@ STR_SCNR :Fort Anachronism STR_PARK :Fort Anachronism STR_DTLS : -##################### -# Rides/attractions # -##################### - -#RCT2 -[TOPSP1] -STR_NAME :Top Spin -STR_DESC :Passengers ride in a gondola suspended by large rotating arms, rotating forwards and backwards head-over-heels -STR_CPTY :8 passengers - -[BMSD] -STR_NAME :Twister Trains -STR_DESC :A spacious train with shoulder restraints - -[BMSU] -STR_NAME :Stand-up Twister Trains -STR_DESC :A train with shoulder restraints, in which the riders stand up - -[BMFL] -STR_NAME :Floorless Twister Trains -STR_DESC :A spacious train with shoulder restraints and no floor, making for a more exciting ride - -[WMMINE] -STR_NAME :Mine Cars -STR_DESC :Cars shaped like an old mine cart - -[WMOUSE] -STR_NAME :Mouse Cars -STR_DESC :Indivual cars shaped like a mouse - -[STEEP1] -STR_NAME :Horses -STR_DESC :Single cars shaped like a horse - -[STEEP2] -STR_NAME :Motorbikes -STR_DESC :Single cars shaped like a motorbike - -[SBOX] -STR_NAME :Soap boxes -STR_DESC :Single cars shaped like a soap box - -[BOB1] -STR_NAME :Bobsleigh Trains -STR_DESC :A train consisting of 2-seater cars where the riders are behind each other - -[INTBOB] -STR_NAME :6-seater Bobsleighs -STR_DESC :Bobsleighs with three seating rows, with room for two people on each - -[LIFT1] -STR_NAME :Lift Cabin -STR_DESC :Steel lift cabin - -[ARRT1] -STR_NAME :Corkscrew Roller Coaster Trains -STR_DESC :Roller coaster train with shoulder restraints - -[ARRT2] -STR_NAME :Hypercoaster Trains -STR_DESC :Comfortable trains with only lap bar restraints - -[MONBK] -STR_NAME :Bicycles - -[OBS1] -STR_NAME :Single-deck Cabin - -[OBS2] -STR_NAME :Double-deck Cabin - -[GTC] -STR_NAME :Ghost Train Cars - -[HMCAR] -STR_NAME :Haunted Mansion Cars - -[VREEL] -STR_NAME :Virginia Reel tubs - -[WMSPIN] -STR_NAME :Spinning Mouse Cars - -[AMT1] -STR_NAME :Mine Trains - -[SLCT] -STR_NAME :Compact Inverted Coaster Trains - -[SLCFO] -STR_NAME :Face-off Cars - -[VEKDV] -STR_NAME :Vertical Shuttle Cars - -[THCAR] -STR_NAME :Air Powered Vertical Coaster Trains - -[SSC1] -STR_NAME :Launched Freefall car - -[DING1] -STR_NAME :Dinghies - -[LFB1] -STR_NAME :Logs - -[RFTBOAT] -STR_NAME :Rafts - -[IVMC1] -STR_NAME :Four-seater Cars - -[SPDRCR] -STR_NAME :Spiral Roller Coaster Trains - -[TOGST] -STR_NAME :Stand-up Roller Coaster Trains - -[PREMT1] -STR_NAME :LIM Launched Roller Coaster Trains - -[PMT1] -STR_NAME :Powered mine train - -[BMAIR] -STR_NAME :Flying Roller Coaster Trains - -[INTINV] -STR_NAME :Impulse Trains - -[INTST] -STR_NAME :Giga Coaster Trains - -[NEMT] -STR_NAME :4-across Inverted Roller Coaster Trains - -[VEKST] -STR_NAME :Lay-down Roller Coaster Trains - -[REVCAR] -STR_NAME :Reverser Cars -STR_DESC :Bogied cars capable of turning around on special reversing sections - -[SKYTR] -STR_NAME :Lay-down Cars - -[BMVD] -STR_NAME :Six-seater Twister Trains - -[SUBMAR] -STR_NAME :Submarines - -# Spelling -[CINDR] -STR_NAME :Sujeonggwa Stall -STR_DESC :A stall selling Korean style Sujeonggwa drinks - -#WW -[CONDORRD] -STR_NAME :Condor Trains -STR_DESC :Riding in special harnesses below the track, riders experience the feeling of flight as they swoop through the air in Condor-shaped trains -STR_CPTY :4 passengers per car - -#WW -[CONGAEEL] -STR_NAME :Conger Eel Trains -STR_DESC :Trains with shoulder restraints, in the shape of a Conger Eel. - -#WW -[MINELIFT] -STR_NAME :Mine Lift Cabin -STR_DESC :A steel lift cabin commonly used in mines - -#WW -[ANACONDA] -STR_NAME :Anaconda Trains - -#WW -[CROCFLUM] -STR_NAME :Crocodile boats - -#WW -[WHICGRUB] -STR_NAME :Witchity Grub Trains - -#WW -[GRATWHTE] -STR_NAME :Great White Shark Trains -STR_DESC :Trains with shoulder restraints, in the shape of a Great White Shark - -#WW -[BOMERANG] -STR_NAME :Boomerang Trains - -#WW -[KOLARIDE] -STR_NAME :Koala car - -#WW -[MANTARAY] -STR_NAME :Manta Ray boats -STR_DESC :Coaster boats in the shape of a Manta Ray - -#WW -[TUTLBOAT] -STR_NAME :Turtle boats - -#WW, for the Wooden RC -[MINECART] -STR_NAME :Mine Cart Trains - -#WW -[LIONRIDE] -STR_NAME :Lion Cars - -#WW -[RHINORID] -STR_NAME :Rhino Trains - -#WW -[OSTRICH] -STR_NAME :Ostrich Trains - -#WW -[GORILLA] -STR_NAME :Gorilla Trains - -#WW -[FOOTBALL] -STR_NAME :Football Trains - -#WW -[TIGRTWST] -STR_NAME :Bengal Tiger Cars - -#WW -[TAXICSTR] -STR_NAME :Yellow Taxi Trains - -#WW -[OUTRIGGR] -STR_NAME :Outrigger canoes - -#WW -[SANFTRAM] -STR_NAME :San Francisco Trams - -#WW -[PENGUINB] -STR_NAME :Penguin Trains - -#WW -[POLARBER] -STR_NAME :Polar Bear Trains - -#WW -[LONDONBS] -STR_NAME :Routemaster buses -STR_DESC :Replicas of the famous London Routemaster bus - -#WW -[BLACKCAB] -STR_NAME :Black Cabs - -#WW -[TGVTRAIN] -STR_NAME :TGV Trains - -#WW -[ROCKET] -STR_NAME :1950's Rockets - -#WW -[SPUTNIKR] -STR_NAME :Sputnik Cars - -#WW -[DHOWWATR] -STR_NAME :Dhow boats - -#WW -[SURFBRDC] -STR_NAME :Surfing Trains - -#WW -[KILLWHAL] -STR_NAME :Killer Whale Submarines - -#WW -[HIPPORID] -STR_NAME :Hippo Submarines - -#WW -[DOLPHINR] -STR_NAME :Dolphin boats - -#WW -[MANDARIN] -STR_NAME :Mandarin Duck Boats -STR_DESC :Duck shaped boat, propelled by the pedalling front seat passengers - -#TT -[BATTRRAM] -STR_NAME :Battering Ram Trains - -#TT -[BLCKDETH] -STR_NAME :Black Death Trains - -#TT -[JOUSTING] -STR_NAME :Jousting Knights - -#TT -[OAKBAREL] -STR_NAME :Oak Barrels - -#TT -[STAMPHRD] -STR_NAME :Stampeding Herd Trains - -#TT -[DRAGNFLY] -STR_NAME :Dragonfly Cars - -#TT -[PTERODAC] -STR_NAME :Pterodactyl Trains - -#TT -[PEGASUSX] -STR_NAME :Pegasus Cars - -#TT -[CERBERUS] -STR_NAME :Cerberus Trains - -#TT -[HARPIESX] -STR_NAME :Harpies Trains - -#TT -[VALKYRIE] -STR_NAME :Valkyries Trains - -#TT -[RIVRSTYX] -STR_NAME :River Styx boats - -#TT -[TELEPTER] -STR_NAME :Teleporter Cabin - -#TT -[HOVERCAR] -STR_NAME :Hover Cars - -#TT -[HOVRBORD] -STR_NAME :Hoverboards - -#TT -[HOVERBKE] -STR_NAME :Hover Bikes - -#TT, Reverser RC -[POLICECR] -STR_NAME :Police Cars - -#TT, Looping RC -[POLCHASE] -STR_NAME :Police Car Trains - -#TT -[GANSTRCR] -STR_NAME :Gangster Cars - -#TT -[SEAPLANE] -STR_NAME :Suspended Seaplane Cars - -#TT -[BARNSTRM] -STR_NAME :BarnStorming Cars - -#TT -[FLYGBOAT] -STR_NAME :Flying boats - -#TT -[BMVOCTPS] -STR_NAME :Blob from Outer Space - -#TT -[JETPLANE] -STR_NAME :Jet Plane Cars - -#TT -[HOTRODXX] -STR_NAME :Hot Rod Cars - ########### # Scenery # ########### -#Bulrushes was spelt incorrectly -[TBR] -STR_NAME :Bulrushes - ## Start OpenRCT2 Official [XXBBBR01] STR_NAME :Base Block From 855baadd4ce2dc53c14ed4c4c2f391682de4234a Mon Sep 17 00:00:00 2001 From: Michael Steenbeek Date: Thu, 29 Mar 2018 14:31:17 +0200 Subject: [PATCH 85/93] Remove incorrect sujeonggwa spelling --- src/openrct2/object/RideObject.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/openrct2/object/RideObject.cpp b/src/openrct2/object/RideObject.cpp index 74754f69a7..4184880697 100644 --- a/src/openrct2/object/RideObject.cpp +++ b/src/openrct2/object/RideObject.cpp @@ -1054,7 +1054,6 @@ uint8 RideObject::ParseShopItem(const std::string &s) { "iced_tea", SHOP_ITEM_ICED_TEA }, { "fruit_juice", SHOP_ITEM_FRUIT_JUICE }, { "soybean_milk", SHOP_ITEM_SOYBEAN_MILK }, - { "su_jongkwa", SHOP_ITEM_SUJEONGGWA }, { "sujeonggwa", SHOP_ITEM_SUJEONGGWA }, { "balloon", SHOP_ITEM_BALLOON }, { "toy", SHOP_ITEM_TOY }, From bc5f253ce2f4721f7e381b0125b2f0b845fd8557 Mon Sep 17 00:00:00 2001 From: Ted John Date: Thu, 29 Mar 2018 17:56:03 +0100 Subject: [PATCH 86/93] Update objects to latest v1.0 --- CMakeLists.txt | 2 +- openrct2.proj | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 17c75c8342..12e1128288 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,7 +17,7 @@ set(TITLE_SEQUENCE_URL "https://github.com/OpenRCT2/title-sequences/releases/do set(TITLE_SEQUENCE_SHA1 "1136ef92bfb05cd1cba9831ba6dc4a653d87a246") set(OBJECTS_URL "https://github.com/OpenRCT2/objects/releases/download/v1.0/objects.zip") -set(OBJECTS_SHA1 "5b9dc88b9f42a76d05d1584f10db845247a9b198") +set(OBJECTS_SHA1 "4f670859b5f37f85e0c3d755b1cb75e839c989a6") option(FORCE32 "Force 32-bit build. It will add `-m32` to compiler flags.") option(WITH_TESTS "Build tests") diff --git a/openrct2.proj b/openrct2.proj index 49a9f6d1ec..8854ba62a6 100644 --- a/openrct2.proj +++ b/openrct2.proj @@ -72,7 +72,7 @@ https://github.com/OpenRCT2/title-sequences/releases/download/v0.1.2/title-sequence-v0.1.2.zip 1136ef92bfb05cd1cba9831ba6dc4a653d87a246 https://github.com/OpenRCT2/objects/releases/download/v1.0/objects.zip - 5b9dc88b9f42a76d05d1584f10db845247a9b198 + 4f670859b5f37f85e0c3d755b1cb75e839c989a6 From bb5b531f0c8b88e706a837dcb978476b0c27cbdc Mon Sep 17 00:00:00 2001 From: Ted John Date: Thu, 29 Mar 2018 17:59:49 +0100 Subject: [PATCH 87/93] Use resize instead of push_back --- src/openrct2/object/ObjectJsonHelpers.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/openrct2/object/ObjectJsonHelpers.cpp b/src/openrct2/object/ObjectJsonHelpers.cpp index 66af224fb6..277f003ac1 100644 --- a/src/openrct2/object/ObjectJsonHelpers.cpp +++ b/src/openrct2/object/ObjectJsonHelpers.cpp @@ -275,11 +275,7 @@ namespace ObjectJsonHelpers { std::string msg = "Unable to open '" + objectPath + "'"; context->LogWarning(OBJECT_ERROR_INVALID_PROPERTY, msg.c_str()); - for (size_t i = 0; i < range.size(); i++) - { - auto g1 = rct_g1_element{}; - result.push_back(g1); - } + result.resize(range.size()); } return result; } From 4e44d6ef9c2bfbf3f01d18d15cedb41a6b8d3e6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Janiszewski?= Date: Fri, 30 Mar 2018 13:16:26 +0200 Subject: [PATCH 88/93] Validate alignment of peep_loading_positions at compile time --- src/openrct2/ride/Vehicle.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/openrct2/ride/Vehicle.h b/src/openrct2/ride/Vehicle.h index 9301a48d03..32691cb731 100644 --- a/src/openrct2/ride/Vehicle.h +++ b/src/openrct2/ride/Vehicle.h @@ -17,6 +17,7 @@ #ifndef _VEHICLE_H_ #define _VEHICLE_H_ +#include #include #include "../common.h" #include "../world/Location.hpp" @@ -82,6 +83,7 @@ struct rct_ride_entry_vehicle { std::vector peep_loading_positions; }; #pragma pack(pop) +static_assert(offsetof(rct_ride_entry_vehicle, peep_loading_positions) % 8 == 0); struct rct_vehicle { uint8 sprite_identifier; // 0x00 From 64af3d25d48782de44e749b893fca4706becd011 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Janiszewski?= Date: Fri, 30 Mar 2018 13:42:25 +0200 Subject: [PATCH 89/93] Provide error message for older version of static_assert --- src/openrct2/ride/Vehicle.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/openrct2/ride/Vehicle.h b/src/openrct2/ride/Vehicle.h index 32691cb731..1c7fb95f67 100644 --- a/src/openrct2/ride/Vehicle.h +++ b/src/openrct2/ride/Vehicle.h @@ -83,7 +83,8 @@ struct rct_ride_entry_vehicle { std::vector peep_loading_positions; }; #pragma pack(pop) -static_assert(offsetof(rct_ride_entry_vehicle, peep_loading_positions) % 8 == 0); +static_assert(offsetof(rct_ride_entry_vehicle, peep_loading_positions) % 8 == 0, "Invalid struct layout"); +static_assert(sizeof(rct_ride_entry_vehicle) % 8 == 0, "Invalid struct size"); struct rct_vehicle { uint8 sprite_identifier; // 0x00 From 7443c660257b9ce186eb704725450a5ad379ebde Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Janiszewski?= Date: Fri, 30 Mar 2018 14:05:14 +0200 Subject: [PATCH 90/93] Fix validation of rct_ride_entry_vehicle for 32 bit builds Also enables packing only for testpaint --- src/openrct2/ride/Vehicle.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/openrct2/ride/Vehicle.h b/src/openrct2/ride/Vehicle.h index 1c7fb95f67..86ea757a21 100644 --- a/src/openrct2/ride/Vehicle.h +++ b/src/openrct2/ride/Vehicle.h @@ -27,7 +27,9 @@ struct rct_vehicle_colour { uint8 trim_colour; }; +#ifdef __TESTPAINT__ #pragma pack(push, 1) +#endif // __TESTPAINT__ /** * Ride type vehicle structure. * size: 0x65 @@ -82,9 +84,16 @@ struct rct_ride_entry_vehicle { std::vector peep_loading_positions; }; +#ifdef __TESTPAINT__ #pragma pack(pop) +#endif // __TESTPAINT__ +#ifdef PLATFORM_32BIT +static_assert(offsetof(rct_ride_entry_vehicle, peep_loading_positions) % 4 == 0, "Invalid struct layout"); +static_assert(sizeof(rct_ride_entry_vehicle) % 4 == 0, "Invalid struct size"); +#else static_assert(offsetof(rct_ride_entry_vehicle, peep_loading_positions) % 8 == 0, "Invalid struct layout"); static_assert(sizeof(rct_ride_entry_vehicle) % 8 == 0, "Invalid struct size"); +#endif struct rct_vehicle { uint8 sprite_identifier; // 0x00 From 375deb0c9f1fd331afe40e54def0a7cc9a4e527b Mon Sep 17 00:00:00 2001 From: Ted John Date: Fri, 30 Mar 2018 16:53:55 +0100 Subject: [PATCH 91/93] Include string not cstring --- src/openrct2/object/SceneryObject.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/openrct2/object/SceneryObject.h b/src/openrct2/object/SceneryObject.h index 98ce7256c8..53d40de185 100644 --- a/src/openrct2/object/SceneryObject.h +++ b/src/openrct2/object/SceneryObject.h @@ -16,7 +16,7 @@ #pragma once -#include +#include #include "Object.h" class SceneryObject : public Object From 63e9275b601b4db2dec6d0bfb9e2c61588cb68b7 Mon Sep 17 00:00:00 2001 From: Ted John Date: Fri, 30 Mar 2018 16:58:12 +0100 Subject: [PATCH 92/93] Protect against unknown ride types --- src/openrct2-ui/windows/EditorObjectSelection.cpp | 3 ++- src/openrct2/core/String.cpp | 6 +++--- src/openrct2/object/RideObject.cpp | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/openrct2-ui/windows/EditorObjectSelection.cpp b/src/openrct2-ui/windows/EditorObjectSelection.cpp index 234b7059a5..314e12a24a 100644 --- a/src/openrct2-ui/windows/EditorObjectSelection.cpp +++ b/src/openrct2-ui/windows/EditorObjectSelection.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -304,7 +305,7 @@ static bool visible_list_sort_ride_type(const list_item &a, const list_item &b) { auto rideTypeA = language_get_string(get_ride_type_string_id(a.repositoryItem)); auto rideTypeB = language_get_string(get_ride_type_string_id(b.repositoryItem)); - sint32 result = strcmp(rideTypeA, rideTypeB); + sint32 result = String::Compare(rideTypeA, rideTypeB); return result != 0 ? result < 0 : visible_list_sort_ride_name(a, b); diff --git a/src/openrct2/core/String.cpp b/src/openrct2/core/String.cpp index ff347f67c9..d9742c4436 100644 --- a/src/openrct2/core/String.cpp +++ b/src/openrct2/core/String.cpp @@ -80,9 +80,9 @@ namespace String sint32 Compare(const utf8 * a, const utf8 * b, bool ignoreCase) { - if (a == b) return true; - if (a == nullptr || b == nullptr) return false; - + if (a == b) return 0; + if (a == nullptr) a = ""; + if (b == nullptr) b = ""; if (ignoreCase) { return _stricmp(a, b); diff --git a/src/openrct2/object/RideObject.cpp b/src/openrct2/object/RideObject.cpp index 4184880697..da7dde5826 100644 --- a/src/openrct2/object/RideObject.cpp +++ b/src/openrct2/object/RideObject.cpp @@ -488,7 +488,7 @@ void RideObject::ReadJson(IReadObjectContext * context, const json_t * root) rideType = ParseRideType(rideTypes[i]); if (rideType == RIDE_TYPE_NULL) { - context->LogWarning(OBJECT_ERROR_INVALID_PROPERTY, "Unknown ride type"); + context->LogError(OBJECT_ERROR_INVALID_PROPERTY, "Unknown ride type"); } } From 4c9d047b5299157d22f009b18f3be92fdea6e6a9 Mon Sep 17 00:00:00 2001 From: Ted John Date: Fri, 6 Apr 2018 10:45:08 +0100 Subject: [PATCH 93/93] Update android build to download objects --- src/openrct2-android/app/build.gradle | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/openrct2-android/app/build.gradle b/src/openrct2-android/app/build.gradle index d4ca61018a..4627d953b3 100644 --- a/src/openrct2-android/app/build.gradle +++ b/src/openrct2-android/app/build.gradle @@ -90,6 +90,14 @@ android.applicationVariants.all { variant -> from zipTree(new File(buildDir, 'title-sequence.zip')) into "$variant.mergeAssets.outputDir/data/title" } + download { + src 'https://github.com/OpenRCT2/objects/releases/download/v1.0/objects.zip' + dest new File(buildDir, 'objects.zip') + } + copy { + from zipTree(new File(buildDir, 'objects.zip')) + into "$variant.mergeAssets.outputDir/data/object" + } } }