Implement S4 restricted scenery

This commit is contained in:
Ted John 2021-04-29 01:07:32 +01:00
parent 37725ae566
commit 5c8512f51c
7 changed files with 192 additions and 2 deletions

View File

@ -187,7 +187,7 @@ static void init_scenery_entry(
{
Guard::ArgumentInRange<int32_t>(selection.EntryIndex, 0, OBJECT_ENTRY_INDEX_NULL);
if (gCheatsIgnoreResearchStatus || scenery_is_invented(selection))
if (IsSceneryAvailableToBuild(selection))
{
// Check if in any other groups
for (const auto& otherTab : _tabEntries)
@ -296,7 +296,7 @@ static void window_scenery_init(rct_window* w)
for (size_t i = 0; i < sceneryGroupEntry->entry_count; i++)
{
auto sceneryEntry = sceneryGroupEntry->scenery_entries[i];
if (scenery_is_invented(sceneryEntry) || gCheatsIgnoreResearchStatus)
if (IsSceneryAvailableToBuild(sceneryEntry))
{
tabInfo.Entries.push_back(sceneryEntry);
}

View File

@ -78,6 +78,9 @@ void GameState::InitAll(int32_t mapSize)
context_broadcast_intent(&intent);
load_palette();
CheatsReset();
ClearRestrictedScenery();
}
/**

View File

@ -84,6 +84,7 @@ namespace OpenRCT2
constexpr uint32_t BANNERS = 0x33;
// constexpr uint32_t STAFF = 0x35;
constexpr uint32_t CHEATS = 0x36;
constexpr uint32_t RESTRICTED_OBJECTS = 0x37;
constexpr uint32_t PACKED_OBJECTS = 0x80;
// clang-format on
}; // namespace ParkFileChunkType
@ -128,6 +129,7 @@ namespace OpenRCT2
ReadWriteNotificationsChunk(os);
ReadWriteInterfaceChunk(os);
ReadWriteCheatsChunk(os);
ReadWriteRestrictedObjectsChunk(os);
// Initial cash will eventually be removed
gInitialCash = gCash;
@ -156,6 +158,7 @@ namespace OpenRCT2
ReadWriteNotificationsChunk(os);
ReadWriteInterfaceChunk(os);
ReadWriteCheatsChunk(os);
ReadWriteRestrictedObjectsChunk(os);
ReadWritePackedObjectsChunk(os);
}
@ -438,6 +441,28 @@ namespace OpenRCT2
});
}
void ReadWriteRestrictedObjectsChunk(OrcaStream& os)
{
os.ReadWriteChunk(ParkFileChunkType::RESTRICTED_OBJECTS, [](OrcaStream::ChunkStream& cs) {
auto& restrictedScenery = GetRestrictedScenery();
// We are want to support all object types in the future, so convert scenery type
// to object type when we write the list
cs.ReadWriteVector(restrictedScenery, [&cs](ScenerySelection& item) {
if (cs.GetMode() == OrcaStream::Mode::READING)
{
item.SceneryType = GetSceneryTypeFromObjectType(static_cast<ObjectType>(cs.Read<uint16_t>()));
item.EntryIndex = cs.Read<ObjectEntryIndex>();
}
else
{
cs.Write(static_cast<uint16_t>(GetObjectTypeFromSceneryType(item.SceneryType)));
cs.Write(item.EntryIndex);
}
});
});
}
void ReadWritePackedObjectsChunk(OrcaStream& os)
{
static constexpr uint8_t DESCRIPTOR_DAT = 0;

View File

@ -219,6 +219,8 @@ public:
research_determine_first_of_type();
CheatsReset();
ClearRestrictedScenery();
RestrictAllMiscScenery();
}
bool GetDetails(scenario_index_entry* dst) override

View File

@ -480,6 +480,7 @@ public:
research_determine_first_of_type();
CheatsReset();
ClearRestrictedScenery();
}
void ImportRides()

View File

@ -26,6 +26,7 @@
#include "Climate.h"
#include "Footpath.h"
#include "Fountain.h"
#include "LargeScenery.h"
#include "Map.h"
#include "Park.h"
#include "SmallScenery.h"
@ -52,6 +53,8 @@ int16_t gSceneryCtrlPressZ;
money32 gClearSceneryCost;
static std::vector<ScenerySelection> _restrictedScenery;
// rct2: 0x009A3E74
const CoordsXY SceneryQuadrantOffsets[] = { { 7, 7 }, { 7, 23 }, { 23, 23 }, { 23, 7 } };
@ -281,3 +284,149 @@ int32_t wall_entry_get_door_sound(const rct_scenery_entry* wallEntry)
{
return (wallEntry->wall.flags2 & WALL_SCENERY_2_DOOR_SOUND_MASK) >> WALL_SCENERY_2_DOOR_SOUND_SHIFT;
}
bool IsSceneryAvailableToBuild(ScenerySelection item)
{
if (!gCheatsIgnoreResearchStatus)
{
if (!scenery_is_invented(item))
{
return false;
}
}
if (!gCheatsSandboxMode)
{
if (IsSceneryItemRestricted(item))
{
return false;
}
}
return true;
}
static ObjectEntryIndex GetMaxObjectsForSceneryType(uint8_t sceneryType)
{
switch (sceneryType)
{
case SCENERY_TYPE_SMALL:
return MAX_SMALL_SCENERY_OBJECTS;
case SCENERY_TYPE_PATH_ITEM:
return MAX_PATH_ADDITION_OBJECTS;
case SCENERY_TYPE_WALL:
return MAX_WALL_SCENERY_OBJECTS;
case SCENERY_TYPE_LARGE:
return MAX_LARGE_SCENERY_OBJECTS;
case SCENERY_TYPE_BANNER:
return MAX_BANNER_OBJECTS;
default:
return 0;
}
}
static rct_scenery_entry* GetSceneryEntry(ScenerySelection item)
{
switch (item.SceneryType)
{
case SCENERY_TYPE_SMALL:
return get_small_scenery_entry(item.EntryIndex);
case SCENERY_TYPE_PATH_ITEM:
return get_footpath_item_entry(item.EntryIndex);
case SCENERY_TYPE_WALL:
return get_wall_entry(item.EntryIndex);
case SCENERY_TYPE_LARGE:
return get_large_scenery_entry(item.EntryIndex);
case SCENERY_TYPE_BANNER:
return get_banner_entry(item.EntryIndex);
default:
return nullptr;
}
}
bool IsSceneryItemRestricted(ScenerySelection item)
{
auto it = std::find(_restrictedScenery.begin(), _restrictedScenery.end(), item);
return it != _restrictedScenery.end();
}
void ClearRestrictedScenery()
{
_restrictedScenery.clear();
}
std::vector<ScenerySelection>& GetRestrictedScenery()
{
return _restrictedScenery;
}
void RestrictAllMiscScenery()
{
std::vector<ScenerySelection> nonMiscScenery;
for (ObjectEntryIndex i = 0; i < MAX_SCENERY_GROUP_OBJECTS; i++)
{
auto sgEntry = get_scenery_group_entry(i);
if (sgEntry != nullptr)
{
for (size_t j = 0; j < sgEntry->entry_count; j++)
{
nonMiscScenery.push_back(sgEntry->scenery_entries[j]);
}
}
}
for (uint8_t sceneryType = SCENERY_TYPE_SMALL; sceneryType < SCENERY_TYPE_COUNT; sceneryType++)
{
auto maxObjects = GetMaxObjectsForSceneryType(sceneryType);
for (ObjectEntryIndex i = 0; i < maxObjects; i++)
{
ScenerySelection sceneryItem = { sceneryType, i };
auto sceneryEntry = GetSceneryEntry(sceneryItem);
if (sceneryEntry != nullptr)
{
auto it = std::find(nonMiscScenery.begin(), nonMiscScenery.end(), sceneryItem);
if (it == nonMiscScenery.end())
{
_restrictedScenery.push_back(sceneryItem);
}
}
}
}
}
ObjectType GetObjectTypeFromSceneryType(uint8_t type)
{
switch (type)
{
case SCENERY_TYPE_SMALL:
return ObjectType::SmallScenery;
case SCENERY_TYPE_PATH_ITEM:
return ObjectType::PathBits;
case SCENERY_TYPE_WALL:
return ObjectType::Walls;
case SCENERY_TYPE_LARGE:
return ObjectType::LargeScenery;
case SCENERY_TYPE_BANNER:
return ObjectType::Banners;
default:
throw std::runtime_error("Invalid scenery type");
}
}
uint8_t GetSceneryTypeFromObjectType(ObjectType type)
{
switch (type)
{
case ObjectType::SmallScenery:
return SCENERY_TYPE_SMALL;
case ObjectType::PathBits:
return SCENERY_TYPE_PATH_ITEM;
case ObjectType::Walls:
return SCENERY_TYPE_WALL;
case ObjectType::LargeScenery:
return SCENERY_TYPE_LARGE;
case ObjectType::Banners:
return SCENERY_TYPE_BANNER;
default:
throw std::runtime_error("Invalid object type");
}
}

View File

@ -264,4 +264,14 @@ rct_scenery_group_entry* get_scenery_group_entry(ObjectEntryIndex entryIndex);
int32_t wall_entry_get_door_sound(const rct_scenery_entry* wallEntry);
bool IsSceneryAvailableToBuild(ScenerySelection item);
bool IsSceneryItemRestricted(ScenerySelection item);
void ClearRestrictedScenery();
void RestrictAllMiscScenery();
std::vector<ScenerySelection>& GetRestrictedScenery();
ObjectType GetObjectTypeFromSceneryType(uint8_t type);
uint8_t GetSceneryTypeFromObjectType(ObjectType type);
#endif