diff --git a/CMakeLists.txt b/CMakeLists.txt
index 7f5d803b4c..469ca4a1bc 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -50,9 +50,9 @@ set(OBJECTS_VERSION "1.2.1")
set(OBJECTS_URL "https://github.com/OpenRCT2/objects/releases/download/v${OBJECTS_VERSION}/objects.zip")
set(OBJECTS_SHA1 "540e004abc683b3fe22211f5234e3d78ab023c5f")
-set(REPLAYS_VERSION "0.0.47")
+set(REPLAYS_VERSION "0.0.49")
set(REPLAYS_URL "https://github.com/OpenRCT2/replays/releases/download/v${REPLAYS_VERSION}/replays.zip")
-set(REPLAYS_SHA1 "61CAB8A0AD0B057B13B003DF32748977C2B5975F")
+set(REPLAYS_SHA1 "004AE4D38D1326913AF5DE7A90E8AF31DD31BF94")
option(FORCE32 "Force 32-bit build. It will add `-m32` to compiler flags.")
option(WITH_TESTS "Build tests")
diff --git a/distribution/changelog.txt b/distribution/changelog.txt
index 5e5d7651a0..564b7fc02b 100644
--- a/distribution/changelog.txt
+++ b/distribution/changelog.txt
@@ -16,7 +16,9 @@
- Fix: [#15170] Plugin: incorrect label text alignment.
- Fix: [#15184] Crash when hovering over water types in Object Selection.
- Fix: [#15193] Crash when rides/stalls are demolished.
+- Fix: [#15199] Construction window is not closed when a ride gets demolished.
- Fix: [#15255] Tile Inspector shows banner information on walls that do not contain one.
+- Fix: [#15289] Unexpected behavior with duplicated banners which also caused desyncs in multiplayer.
- Improved: [#3417] Crash dumps are now placed in their own folder.
- Change: [#8601] Revert ToonTower base block fix to re-enable support blocking.
- Change: [#15174] [Plugin] Deprecate the type "peep" and add support to target a specific scripting api version.
diff --git a/openrct2.proj b/openrct2.proj
index ec7d572b49..92c3f85094 100644
--- a/openrct2.proj
+++ b/openrct2.proj
@@ -48,8 +48,8 @@
304d13a126c15bf2c86ff13b81a2f2cc1856ac8d
https://github.com/OpenRCT2/objects/releases/download/v1.2.1/objects.zip
540e004abc683b3fe22211f5234e3d78ab023c5f
- https://github.com/OpenRCT2/replays/releases/download/v0.0.47/replays.zip
- 61CAB8A0AD0B057B13B003DF32748977C2B5975F
+ https://github.com/OpenRCT2/replays/releases/download/v0.0.49/replays.zip
+ 004AE4D38D1326913AF5DE7A90E8AF31DD31BF94
diff --git a/src/openrct2-ui/windows/NewRide.cpp b/src/openrct2-ui/windows/NewRide.cpp
index 6bdcc02b25..c601b19dba 100644
--- a/src/openrct2-ui/windows/NewRide.cpp
+++ b/src/openrct2-ui/windows/NewRide.cpp
@@ -33,6 +33,8 @@
#include
#include
+using namespace OpenRCT2::TrackMetaData;
+
static constexpr const rct_string_id WINDOW_TITLE = STR_NONE;
constexpr size_t AVAILABILITY_STRING_SIZE = 256;
static constexpr const int32_t WH = 382;
@@ -941,9 +943,10 @@ static void window_new_ride_paint_ride_information(
if (!(gParkFlags & PARK_FLAGS_NO_MONEY))
{
// Get price of ride
- int32_t unk2 = GetRideTypeDescriptor(item.Type).StartTrackPiece;
+ int32_t startPieceId = GetRideTypeDescriptor(item.Type).StartTrackPiece;
money64 price = GetRideTypeDescriptor(item.Type).BuildCosts.TrackPrice;
- price *= TrackPricing[unk2];
+ const auto& ted = GetTrackElementDescriptor(startPieceId);
+ price *= ted.Price;
price = (price >> 17) * 10 * GetRideTypeDescriptor(item.Type).BuildCosts.PriceEstimateMultiplier;
//
diff --git a/src/openrct2-ui/windows/Ride.cpp b/src/openrct2-ui/windows/Ride.cpp
index 18e364bfb7..26f8809c9c 100644
--- a/src/openrct2-ui/windows/Ride.cpp
+++ b/src/openrct2-ui/windows/Ride.cpp
@@ -59,6 +59,7 @@
#include
using namespace OpenRCT2;
+using namespace OpenRCT2::TrackMetaData;
static constexpr const rct_string_id WINDOW_TITLE = STR_RIDE_WINDOW_TITLE;
static constexpr const int32_t WH = 207;
@@ -1368,7 +1369,8 @@ rct_window* window_ride_open_track(TileElement* tileElement)
// Open ride window in station view
auto trackElement = tileElement->AsTrack();
auto trackType = trackElement->GetTrackType();
- if (TrackSequenceProperties[trackType][0] & TRACK_SEQUENCE_FLAG_ORIGIN)
+ const auto& ted = GetTrackElementDescriptor(trackType);
+ if (ted.SequenceProperties[0] & TRACK_SEQUENCE_FLAG_ORIGIN)
{
auto stationIndex = trackElement->GetStationIndex();
return window_ride_open_station(ride, stationIndex);
diff --git a/src/openrct2-ui/windows/RideConstruction.cpp b/src/openrct2-ui/windows/RideConstruction.cpp
index 52aef8142c..8879ec1607 100644
--- a/src/openrct2-ui/windows/RideConstruction.cpp
+++ b/src/openrct2-ui/windows/RideConstruction.cpp
@@ -42,6 +42,8 @@ static constexpr const int32_t WH = 394;
static constexpr const int32_t WW = 166;
static constexpr const uint16_t ARROW_PULSE_DURATION = 200;
+using namespace OpenRCT2::TrackMetaData;
+
#pragma region Widgets
// clang-format off
@@ -1924,7 +1926,8 @@ static void window_ride_construction_mouseup_demolish(rct_window* w)
return;
}
- const rct_preview_track* trackBlock = TrackBlocks[tileElement->AsTrack()->GetTrackType()];
+ const auto& ted = GetTrackElementDescriptor(tileElement->AsTrack()->GetTrackType());
+ const rct_preview_track* trackBlock = ted.Block;
newCoords->z = (tileElement->GetBaseZ()) - trackBlock->z;
gGotoStartPlacementMode = true;
}
@@ -2346,7 +2349,8 @@ static void window_ride_construction_draw_track_piece(
if (ride == nullptr)
return;
- auto trackBlock = TrackBlocks[trackType];
+ const auto& ted = GetTrackElementDescriptor(trackType);
+ const auto* trackBlock = ted.Block;
while ((trackBlock + 1)->index != 0xFF)
trackBlock++;
@@ -2400,7 +2404,8 @@ static void sub_6CBCE2(
gMapSize = MAXIMUM_MAP_SIZE_TECHNICAL;
- auto trackBlock = TrackBlocks[trackType];
+ const auto& ted = GetTrackElementDescriptor(trackType);
+ const auto* trackBlock = ted.Block;
while (trackBlock->index != 255)
{
auto quarterTile = trackBlock->var_08.Rotate(trackDirection);
@@ -3293,7 +3298,8 @@ static void window_ride_construction_select_map_tiles(
const rct_preview_track* trackBlock;
- trackBlock = TrackBlocks[trackType];
+ const auto& ted = GetTrackElementDescriptor(trackType);
+ trackBlock = ted.Block;
trackDirection &= 3;
gMapSelectionTiles.clear();
while (trackBlock->index != 255)
@@ -3470,7 +3476,8 @@ void ride_construction_toolupdate_construct(const ScreenCoordsXY& screenCoords)
// z = map_get_highest_z(x >> 5, y >> 5);
}
// loc_6CC91B:
- trackBlock = TrackBlocks[trackType];
+ const auto& ted = GetTrackElementDescriptor(trackType);
+ trackBlock = ted.Block;
int32_t bx = 0;
do
{
@@ -3700,7 +3707,8 @@ void ride_construction_tooldown_construct(const ScreenCoordsXY& screenCoords)
if (_trackPlaceZ == 0)
{
- const rct_preview_track* trackBlock = TrackBlocks[_currentTrackPieceType];
+ const auto& ted = GetTrackElementDescriptor(_currentTrackPieceType);
+ const rct_preview_track* trackBlock = ted.Block;
int32_t bx = 0;
do
{
diff --git a/src/openrct2-ui/windows/TrackDesignPlace.cpp b/src/openrct2-ui/windows/TrackDesignPlace.cpp
index 4a3db512f6..58da05f5bd 100644
--- a/src/openrct2-ui/windows/TrackDesignPlace.cpp
+++ b/src/openrct2-ui/windows/TrackDesignPlace.cpp
@@ -32,6 +32,7 @@
#include
using namespace OpenRCT2;
+using namespace OpenRCT2::TrackMetaData;
static constexpr const rct_string_id WINDOW_TITLE = STR_STRING;
static constexpr const int32_t WH = 124;
@@ -550,7 +551,8 @@ static void window_track_place_draw_mini_preview_track(
}
// Follow a single track piece shape
- const rct_preview_track* trackBlock = TrackBlocks[trackType];
+ const auto& ted = GetTrackElementDescriptor(trackType);
+ const rct_preview_track* trackBlock = ted.Block;
while (trackBlock->index != 255)
{
auto rotatedAndOffsetTrackBlock = curTrackStart + CoordsXY{ trackBlock->x, trackBlock->y }.Rotate(curTrackRotation);
@@ -572,9 +574,8 @@ static void window_track_place_draw_mini_preview_track(
auto bits = trackBlock->var_08.Rotate(curTrackRotation & 3).GetBaseQuarterOccupied();
// Station track is a lighter colour
- uint8_t colour = (TrackSequenceProperties[trackType][0] & TRACK_SEQUENCE_FLAG_ORIGIN)
- ? _PaletteIndexColourStation
- : _PaletteIndexColourTrack;
+ uint8_t colour = (ted.SequenceProperties[0] & TRACK_SEQUENCE_FLAG_ORIGIN) ? _PaletteIndexColourStation
+ : _PaletteIndexColourTrack;
for (int32_t i = 0; i < 4; i++)
{
@@ -594,7 +595,8 @@ static void window_track_place_draw_mini_preview_track(
// Change rotation and next position based on track curvature
curTrackRotation &= 3;
- const rct_track_coordinates* track_coordinate = &TrackCoordinates[trackType];
+
+ const rct_track_coordinates* track_coordinate = &ted.Coordinates;
curTrackStart += CoordsXY{ track_coordinate->x, track_coordinate->y }.Rotate(curTrackRotation);
curTrackRotation += track_coordinate->rotation_end - track_coordinate->rotation_begin;
diff --git a/src/openrct2/Context.cpp b/src/openrct2/Context.cpp
index 01a07b8c3f..b4d6e83c0c 100644
--- a/src/openrct2/Context.cpp
+++ b/src/openrct2/Context.cpp
@@ -46,6 +46,7 @@
#include "localisation/Localisation.h"
#include "localisation/LocalisationService.h"
#include "network/DiscordService.h"
+#include "network/NetworkBase.h"
#include "network/network.h"
#include "object/ObjectManager.h"
#include "object/ObjectRepository.h"
@@ -53,6 +54,7 @@
#include "platform/Crash.h"
#include "platform/Platform2.h"
#include "platform/platform.h"
+#include "ride/TrackData.h"
#include "ride/TrackDesignRepository.h"
#include "scenario/Scenario.h"
#include "scenario/ScenarioRepository.h"
@@ -108,6 +110,9 @@ namespace OpenRCT2
#ifdef ENABLE_SCRIPTING
ScriptEngine _scriptEngine;
#endif
+#ifndef DISABLE_NETWORK
+ NetworkBase _network;
+#endif
// Game states
std::unique_ptr _titleScreen;
@@ -149,6 +154,9 @@ namespace OpenRCT2
, _localisationService(std::make_unique(env))
#ifdef ENABLE_SCRIPTING
, _scriptEngine(_stdInOutConsole, *env)
+#endif
+#ifndef DISABLE_NETWORK
+ , _network(*this)
#endif
, _painter(std::make_unique(uiContext))
{
@@ -164,7 +172,9 @@ namespace OpenRCT2
// If objects use GetContext() in their destructor things won't go well.
GameActions::ClearQueue();
- network_close();
+#ifndef DISABLE_NETWORK
+ _network.Close();
+#endif
window_close_all();
// Unload objects after closing all windows, this is to overcome windows like
@@ -256,11 +266,18 @@ namespace OpenRCT2
return _drawingEngine.get();
}
- virtual Paint::Painter* GetPainter() override
+ Paint::Painter* GetPainter() override
{
return _painter.get();
}
+#ifndef DISABLE_NETWORK
+ NetworkBase& GetNetwork() override
+ {
+ return _network;
+ }
+#endif
+
int32_t RunOpenRCT2(int argc, const char** argv) override
{
if (Initialise())
@@ -395,6 +412,7 @@ namespace OpenRCT2
}
_env->SetBasePath(DIRBASE::RCT2, rct2InstallPath);
}
+ TrackMetaData::Init();
_objectRepository = CreateObjectRepository(_env);
_objectManager = CreateObjectManager(*_objectRepository);
@@ -463,7 +481,6 @@ namespace OpenRCT2
gGameSoundsOff = !gConfigSound.master_sound_enabled;
}
- network_set_env(_env);
chat_init();
CopyOriginalUserFilesOver();
@@ -644,40 +661,51 @@ namespace OpenRCT2
gScreenAge = 0;
gLastAutoSaveUpdate = AUTOSAVE_PAUSE;
+#ifndef DISABLE_NETWORK
bool sendMap = false;
+#endif
if (!asScenario && (info.Type == FILE_TYPE::PARK || info.Type == FILE_TYPE::SAVED_GAME))
{
- if (network_get_mode() == NETWORK_MODE_CLIENT)
+#ifndef DISABLE_NETWORK
+ if (_network.GetMode() == NETWORK_MODE_CLIENT)
{
- network_close();
+ _network.Close();
}
+#endif
game_load_init();
- if (network_get_mode() == NETWORK_MODE_SERVER)
+#ifndef DISABLE_NETWORK
+ if (_network.GetMode() == NETWORK_MODE_SERVER)
{
sendMap = true;
}
+#endif
}
else
{
scenario_begin();
- if (network_get_mode() == NETWORK_MODE_SERVER)
+#ifndef DISABLE_NETWORK
+ if (_network.GetMode() == NETWORK_MODE_SERVER)
{
sendMap = true;
}
- if (network_get_mode() == NETWORK_MODE_CLIENT)
+ if (_network.GetMode() == NETWORK_MODE_CLIENT)
{
- network_close();
+ _network.Close();
}
+#endif
}
// This ensures that the newly loaded save reflects the user's
// 'show real names of guests' option, now that it's a global setting
peep_update_names(gConfigGeneral.show_real_names_of_guests);
+#ifndef DISABLE_NETWORK
if (sendMap)
{
- network_send_map();
+ _network.Server_Send_MAP();
}
+#endif
+
#ifdef USE_BREAKPAD
- if (network_get_mode() == NETWORK_MODE_NONE)
+ if (_network.GetMode() == NETWORK_MODE_NONE)
{
start_silent_record();
}
@@ -877,13 +905,13 @@ namespace OpenRCT2
if (String::IsNullOrEmpty(gCustomPassword))
{
- network_set_password(gConfigNetwork.default_password.c_str());
+ _network.SetPassword(gConfigNetwork.default_password.c_str());
}
else
{
- network_set_password(gCustomPassword);
+ _network.SetPassword(gCustomPassword);
}
- network_begin_server(gNetworkStartPort, gNetworkStartAddress);
+ _network.BeginServer(gNetworkStartPort, gNetworkStartAddress);
}
else
#endif // DISABLE_NETWORK
@@ -913,7 +941,7 @@ namespace OpenRCT2
{
gNetworkStartPort = gConfigNetwork.default_port;
}
- network_begin_client(gNetworkStartHost, gNetworkStartPort);
+ _network.BeginClient(gNetworkStartHost, gNetworkStartPort);
}
#endif // DISABLE_NETWORK
diff --git a/src/openrct2/Context.h b/src/openrct2/Context.h
index 5fc83fc521..cbb4529068 100644
--- a/src/openrct2/Context.h
+++ b/src/openrct2/Context.h
@@ -70,6 +70,8 @@ enum
CURSOR_PRESSED = CURSOR_DOWN | CURSOR_CHANGED,
};
+class NetworkBase;
+
namespace OpenRCT2
{
class GameState;
@@ -131,7 +133,9 @@ namespace OpenRCT2
virtual DrawingEngine GetDrawingEngineType() abstract;
virtual Drawing::IDrawingEngine* GetDrawingEngine() abstract;
virtual Paint::Painter* GetPainter() abstract;
-
+#ifndef DISABLE_NETWORK
+ virtual NetworkBase& GetNetwork() abstract;
+#endif
virtual int32_t RunOpenRCT2(int argc, const char** argv) abstract;
virtual bool Initialise() abstract;
diff --git a/src/openrct2/GameStateSnapshots.cpp b/src/openrct2/GameStateSnapshots.cpp
index d3100b8e89..c45ca1b4c4 100644
--- a/src/openrct2/GameStateSnapshots.cpp
+++ b/src/openrct2/GameStateSnapshots.cpp
@@ -337,7 +337,7 @@ struct GameStateSnapshots final : public IGameStateSnapshots
for (int i = 0; i < PEEP_MAX_THOUGHTS; i++)
{
COMPARE_FIELD(Guest, Thoughts[i].type);
- COMPARE_FIELD(Guest, Thoughts[i].argument);
+ COMPARE_FIELD(Guest, Thoughts[i].item);
COMPARE_FIELD(Guest, Thoughts[i].freshness);
COMPARE_FIELD(Guest, Thoughts[i].fresh_timeout);
}
@@ -427,7 +427,6 @@ struct GameStateSnapshots final : public IGameStateSnapshots
COMPARE_FIELD(Vehicle, pad_C6[i]);
}
COMPARE_FIELD(Vehicle, animationState);
- COMPARE_FIELD(Vehicle, var_CA);
COMPARE_FIELD(Vehicle, scream_sound_id);
COMPARE_FIELD(Vehicle, TrackSubposition);
COMPARE_FIELD(Vehicle, num_laps);
diff --git a/src/openrct2/ParkFile.cpp b/src/openrct2/ParkFile.cpp
index 6d45ab0b1f..5a217c278f 100644
--- a/src/openrct2/ParkFile.cpp
+++ b/src/openrct2/ParkFile.cpp
@@ -1522,18 +1522,18 @@ namespace OpenRCT2
cs.ReadWrite(guest->RejoinQueueTimeout);
cs.ReadWrite(guest->PreviousRide);
cs.ReadWrite(guest->PreviousRideTimeOut);
- cs.ReadWriteArray(guest->Thoughts, [&cs](rct_peep_thought& thought) {
+ cs.ReadWriteArray(guest->Thoughts, [&cs](PeepThought& thought) {
cs.ReadWrite(thought.type);
uint8_t item;
cs.ReadWrite(item);
if (item == 255)
{
- thought.argument = std::numeric_limits::max();
+ thought.item = PeepThoughtItemNone;
}
else
{
- thought.argument = item;
+ thought.item = item;
}
cs.ReadWrite(thought.freshness);
@@ -1550,8 +1550,8 @@ namespace OpenRCT2
cs.Ignore();
cs.Ignore();
- std::vector temp;
- cs.ReadWriteVector(temp, [&cs](rct_peep_thought& thought) {
+ std::vector temp;
+ cs.ReadWriteVector(temp, [&cs](PeepThought& thought) {
cs.ReadWrite(thought.type);
cs.ReadWrite(thought.item);
cs.ReadWrite(thought.freshness);
@@ -1743,7 +1743,6 @@ namespace OpenRCT2
cs.ReadWrite(entity.dodgems_collision_direction);
cs.ReadWrite(entity.animation_frame);
cs.ReadWrite(entity.animationState);
- cs.ReadWrite(entity.var_CA);
cs.ReadWrite(entity.scream_sound_id);
cs.ReadWrite(entity.TrackSubposition);
cs.ReadWrite(entity.var_CE);
@@ -1863,9 +1862,9 @@ namespace OpenRCT2
cs.ReadWrite(guest.RejoinQueueTimeout);
cs.ReadWrite(guest.PreviousRide);
cs.ReadWrite(guest.PreviousRideTimeOut);
- cs.ReadWriteArray(guest.Thoughts, [&cs](rct_peep_thought& thought) {
+ cs.ReadWriteArray(guest.Thoughts, [&cs](PeepThought& thought) {
cs.ReadWrite(thought.type);
- cs.ReadWrite(thought.argument);
+ cs.ReadWrite(thought.item);
cs.ReadWrite(thought.freshness);
cs.ReadWrite(thought.fresh_timeout);
return true;
diff --git a/src/openrct2/System.hpp b/src/openrct2/System.hpp
new file mode 100644
index 0000000000..2987df5538
--- /dev/null
+++ b/src/openrct2/System.hpp
@@ -0,0 +1,60 @@
+/*****************************************************************************
+ * Copyright (c) 2014-2021 OpenRCT2 developers
+ *
+ * For a complete list of all authors, please refer to contributors.md
+ * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2
+ *
+ * OpenRCT2 is licensed under the GNU General Public License version 3.
+ *****************************************************************************/
+
+#pragma once
+
+namespace OpenRCT2
+{
+ struct IContext;
+
+ // Base class for systems that are hosted in the Context.
+ class System
+ {
+ IContext& _context;
+
+ public:
+ System(IContext& owner)
+ : _context(owner)
+ {
+ }
+
+ virtual ~System() = default;
+
+ // Called before a tick.
+ virtual void PreTick()
+ {
+ }
+
+ // Called every game tick, which by default is 40hz.
+ virtual void Tick()
+ {
+ }
+
+ // Called after a tick.
+ virtual void PostTick()
+ {
+ }
+
+ // Called every frame.
+ virtual void Update()
+ {
+ }
+
+ IContext& GetContext()
+ {
+ return _context;
+ }
+
+ const IContext& GetContext() const
+ {
+ return _context;
+ }
+ };
+
+} // namespace OpenRCT2
diff --git a/src/openrct2/actions/MazePlaceTrackAction.cpp b/src/openrct2/actions/MazePlaceTrackAction.cpp
index aa394ea0ea..c62e469524 100644
--- a/src/openrct2/actions/MazePlaceTrackAction.cpp
+++ b/src/openrct2/actions/MazePlaceTrackAction.cpp
@@ -12,6 +12,8 @@
#include "../ride/RideData.h"
#include "../ride/TrackData.h"
+using namespace OpenRCT2::TrackMetaData;
+
MazePlaceTrackAction::MazePlaceTrackAction(const CoordsXYZ& location, NetworkRideId_t rideIndex, uint16_t mazeEntry)
: _loc(location)
, _rideIndex(rideIndex)
@@ -113,7 +115,8 @@ GameActions::Result::Ptr MazePlaceTrackAction::Query() const
return res;
}
- money32 price = (((ride->GetRideTypeDescriptor().BuildCosts.TrackPrice * TrackPricing[TrackElemType::Maze]) >> 16));
+ const auto& ted = GetTrackElementDescriptor(TrackElemType::Maze);
+ money32 price = (((ride->GetRideTypeDescriptor().BuildCosts.TrackPrice * ted.Price) >> 16));
res->Cost = canBuild->Cost + price / 2 * 10;
return res;
@@ -154,7 +157,8 @@ GameActions::Result::Ptr MazePlaceTrackAction::Execute() const
return canBuild;
}
- money32 price = (((ride->GetRideTypeDescriptor().BuildCosts.TrackPrice * TrackPricing[TrackElemType::Maze]) >> 16));
+ const auto& ted = GetTrackElementDescriptor(TrackElemType::Maze);
+ money32 price = (((ride->GetRideTypeDescriptor().BuildCosts.TrackPrice * ted.Price) >> 16));
res->Cost = canBuild->Cost + price / 2 * 10;
auto startLoc = _loc.ToTileStart();
diff --git a/src/openrct2/actions/MazeSetTrackAction.cpp b/src/openrct2/actions/MazeSetTrackAction.cpp
index d2755adb1c..f0dd07396f 100644
--- a/src/openrct2/actions/MazeSetTrackAction.cpp
+++ b/src/openrct2/actions/MazeSetTrackAction.cpp
@@ -21,6 +21,8 @@
#include "../world/Footpath.h"
#include "../world/Park.h"
+using namespace OpenRCT2::TrackMetaData;
+
MazeSetTrackAction::MazeSetTrackAction(
const CoordsXYZD& location, bool initialPlacement, NetworkRideId_t rideIndex, uint8_t mode)
: _loc(location)
@@ -134,7 +136,8 @@ GameActions::Result::Ptr MazeSetTrackAction::Query() const
return res;
}
- money32 price = (((ride->GetRideTypeDescriptor().BuildCosts.TrackPrice * TrackPricing[TrackElemType::Maze]) >> 16));
+ const auto& ted = GetTrackElementDescriptor(TrackElemType::Maze);
+ money32 price = (((ride->GetRideTypeDescriptor().BuildCosts.TrackPrice * ted.Price) >> 16));
res->Cost = price / 2 * 10;
return res;
@@ -169,7 +172,8 @@ GameActions::Result::Ptr MazeSetTrackAction::Execute() const
auto tileElement = map_get_track_element_at_of_type_from_ride(_loc, TrackElemType::Maze, _rideIndex);
if (tileElement == nullptr)
{
- money32 price = (((ride->GetRideTypeDescriptor().BuildCosts.TrackPrice * TrackPricing[TrackElemType::Maze]) >> 16));
+ const auto& ted = GetTrackElementDescriptor(TrackElemType::Maze);
+ money32 price = (((ride->GetRideTypeDescriptor().BuildCosts.TrackPrice * ted.Price) >> 16));
res->Cost = price / 2 * 10;
auto startLoc = _loc.ToTileStart();
diff --git a/src/openrct2/actions/RideDemolishAction.cpp b/src/openrct2/actions/RideDemolishAction.cpp
index 3add2042dc..ecc24ea6ce 100644
--- a/src/openrct2/actions/RideDemolishAction.cpp
+++ b/src/openrct2/actions/RideDemolishAction.cpp
@@ -157,10 +157,7 @@ GameActions::Result::Ptr RideDemolishAction::DemolishRide(Ride* ride) const
gParkValue = GetContext()->GetGameState()->GetPark().CalculateParkValue();
// Close windows related to the demolished ride
- if (!(GetFlags() & GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED))
- {
- window_close_by_number(WC_RIDE_CONSTRUCTION, _rideIndex);
- }
+ window_close_by_number(WC_RIDE_CONSTRUCTION, _rideIndex);
window_close_by_number(WC_RIDE, _rideIndex);
window_close_by_number(WC_DEMOLISH_RIDE_PROMPT, _rideIndex);
window_close_by_class(WC_NEW_CAMPAIGN);
diff --git a/src/openrct2/actions/TrackPlaceAction.cpp b/src/openrct2/actions/TrackPlaceAction.cpp
index ec4ce6cb29..2f36dfc5c8 100644
--- a/src/openrct2/actions/TrackPlaceAction.cpp
+++ b/src/openrct2/actions/TrackPlaceAction.cpp
@@ -19,6 +19,7 @@
#include "../world/Surface.h"
#include "RideSetSettingAction.h"
+using namespace OpenRCT2::TrackMetaData;
TrackPlaceActionResult::TrackPlaceActionResult()
: GameActions::Result(GameActions::Status::Ok, STR_RIDE_CONSTRUCTION_CANT_CONSTRUCT_THIS_HERE)
{
@@ -146,7 +147,8 @@ GameActions::Result::Ptr TrackPlaceAction::Query() const
if ((_trackPlaceFlags & CONSTRUCTION_LIFT_HILL_SELECTED)
&& !ride->GetRideTypeDescriptor().SupportsTrackPiece(TRACK_LIFT_HILL_STEEP) && !gCheatsEnableChainLiftOnAllTrack)
{
- if (TrackFlags[_trackType] & TRACK_ELEM_FLAG_IS_STEEP_UP)
+ const auto& ted = GetTrackElementDescriptor(_trackType);
+ if (ted.Flags & TRACK_ELEM_FLAG_IS_STEEP_UP)
{
return std::make_unique(GameActions::Status::Disallowed, STR_TOO_STEEP_FOR_LIFT_HILL);
}
@@ -154,7 +156,8 @@ GameActions::Result::Ptr TrackPlaceAction::Query() const
}
money32 cost = 0;
- const rct_preview_track* trackBlock = TrackBlocks[_trackType];
+ const auto& ted = GetTrackElementDescriptor(_trackType);
+ const rct_preview_track* trackBlock = ted.Block;
uint32_t numElements = 0;
// First check if any of the track pieces are outside the park
for (; trackBlock->index != 0xFF; trackBlock++)
@@ -174,9 +177,10 @@ GameActions::Result::Ptr TrackPlaceAction::Query() const
log_warning("Not enough free map elements to place track.");
return std::make_unique(GameActions::Status::NoFreeElements, STR_TILE_ELEMENT_LIMIT_REACHED);
}
+
if (!gCheatsAllowTrackPlaceInvalidHeights)
{
- if (TrackFlags[_trackType] & TRACK_ELEM_FLAG_STARTS_AT_HALF_HEIGHT)
+ if (ted.Flags & TRACK_ELEM_FLAG_STARTS_AT_HALF_HEIGHT)
{
if ((_origin.z & 0x0F) != 8)
{
@@ -195,7 +199,7 @@ GameActions::Result::Ptr TrackPlaceAction::Query() const
}
// If that is not the case, then perform the remaining checks
- trackBlock = TrackBlocks[_trackType];
+ trackBlock = ted.Block;
for (int32_t blockIndex = 0; trackBlock->index != 0xFF; trackBlock++, blockIndex++)
{
@@ -259,8 +263,7 @@ GameActions::Result::Ptr TrackPlaceAction::Query() const
}
res->GroundFlags = mapGroundFlags;
-
- if (TrackFlags[_trackType] & TRACK_ELEM_FLAG_ONLY_ABOVE_GROUND)
+ if (ted.Flags & TRACK_ELEM_FLAG_ONLY_ABOVE_GROUND)
{
if (res->GroundFlags & ELEMENT_IS_UNDERGROUND)
{
@@ -269,7 +272,7 @@ GameActions::Result::Ptr TrackPlaceAction::Query() const
}
}
- if (TrackFlags[_trackType] & TRACK_ELEM_FLAG_ONLY_UNDERWATER)
+ if (ted.Flags & TRACK_ELEM_FLAG_ONLY_UNDERWATER)
{ // No element has this flag
if (canBuild->GroundFlags & ELEMENT_IS_UNDERWATER)
{
@@ -315,7 +318,7 @@ GameActions::Result::Ptr TrackPlaceAction::Query() const
}
}
- int32_t entranceDirections = TrackSequenceProperties[_trackType][0];
+ int32_t entranceDirections = ted.SequenceProperties[0];
if ((entranceDirections & TRACK_SEQUENCE_FLAG_ORIGIN) && trackBlock->index == 0)
{
if (!track_add_station_element({ mapLoc, baseZ, _origin.direction }, _rideIndex, 0, _fromTrackDesign))
@@ -364,7 +367,7 @@ GameActions::Result::Ptr TrackPlaceAction::Query() const
}
money32 price = ride->GetRideTypeDescriptor().BuildCosts.TrackPrice;
- price *= TrackPricing[_trackType];
+ price *= ted.Price;
price >>= 16;
res->Cost = cost + ((price / 2) * 10);
@@ -397,13 +400,11 @@ GameActions::Result::Ptr TrackPlaceAction::Execute() const
uint32_t rideTypeFlags = ride->GetRideTypeDescriptor().Flags;
- const uint8_t(*wallEdges)[16];
- wallEdges = &TrackSequenceElementAllowedWallEdges[_trackType];
+ const auto& ted = GetTrackElementDescriptor(_trackType);
+ const auto& wallEdges = ted.SequenceElementAllowedWallEdges;
money32 cost = 0;
- const rct_preview_track* trackBlock = TrackBlocks[_trackType];
-
- trackBlock = TrackBlocks[_trackType];
+ const rct_preview_track* trackBlock = ted.Block;
for (int32_t blockIndex = 0; trackBlock->index != 0xFF; trackBlock++, blockIndex++)
{
auto rotatedTrack = CoordsXYZ{ CoordsXY{ trackBlock->x, trackBlock->y }.Rotate(_origin.direction), trackBlock->z };
@@ -450,7 +451,7 @@ GameActions::Result::Ptr TrackPlaceAction::Execute() const
else
{
// Remove walls in the directions this track intersects
- uint8_t intersectingDirections = (*wallEdges)[blockIndex];
+ uint8_t intersectingDirections = wallEdges[blockIndex];
intersectingDirections ^= 0x0F;
intersectingDirections = rol4(intersectingDirections, _origin.direction);
for (int32_t i = 0; i < NumOrthogonalDirections; i++)
@@ -537,7 +538,7 @@ GameActions::Result::Ptr TrackPlaceAction::Execute() const
{
if (!(GetFlags() & GAME_COMMAND_FLAG_NO_SPEND))
{
- entranceDirections = TrackSequenceProperties[_trackType][0];
+ entranceDirections = ted.SequenceProperties[0];
}
}
@@ -596,7 +597,7 @@ GameActions::Result::Ptr TrackPlaceAction::Execute() const
}
trackElement->SetColourScheme(_colour);
- entranceDirections = TrackSequenceProperties[_trackType][0];
+ entranceDirections = ted.SequenceProperties[0];
if (entranceDirections & TRACK_SEQUENCE_FLAG_CONNECTS_TO_PATH)
{
uint8_t availableDirections = entranceDirections & 0x0F;
@@ -652,7 +653,7 @@ GameActions::Result::Ptr TrackPlaceAction::Execute() const
}
money32 price = ride->GetRideTypeDescriptor().BuildCosts.TrackPrice;
- price *= TrackPricing[_trackType];
+ price *= ted.Price;
price >>= 16;
res->Cost = cost + ((price / 2) * 10);
@@ -661,7 +662,8 @@ GameActions::Result::Ptr TrackPlaceAction::Execute() const
bool TrackPlaceAction::CheckMapCapacity(int16_t numTiles) const
{
- for (const rct_preview_track* trackBlock = TrackBlocks[_trackType]; trackBlock->index != 0xFF; trackBlock++)
+ const auto& ted = GetTrackElementDescriptor(_trackType);
+ for (const rct_preview_track* trackBlock = ted.Block; trackBlock->index != 0xFF; trackBlock++)
{
auto rotatedTrack = CoordsXY{ trackBlock->x, trackBlock->y }.Rotate(_origin.direction);
diff --git a/src/openrct2/actions/TrackRemoveAction.cpp b/src/openrct2/actions/TrackRemoveAction.cpp
index 0165bb721f..8e1bf2b942 100644
--- a/src/openrct2/actions/TrackRemoveAction.cpp
+++ b/src/openrct2/actions/TrackRemoveAction.cpp
@@ -19,6 +19,8 @@
#include "../world/Surface.h"
#include "RideSetSettingAction.h"
+using namespace OpenRCT2::TrackMetaData;
+
TrackRemoveAction::TrackRemoveAction(track_type_t trackType, int32_t sequence, const CoordsXYZD& origin)
: _trackType(trackType)
, _sequence(sequence)
@@ -120,7 +122,7 @@ GameActions::Result::Ptr TrackRemoveAction::Query() const
}
ride_id_t rideIndex = tileElement->AsTrack()->GetRideIndex();
- auto trackType = tileElement->AsTrack()->GetTrackType();
+ const auto trackType = tileElement->AsTrack()->GetTrackType();
auto ride = get_ride(rideIndex);
if (ride == nullptr)
@@ -134,7 +136,8 @@ GameActions::Result::Ptr TrackRemoveAction::Query() const
log_warning("Ride type not found. ride type = %d.", ride->type);
return MakeResult(GameActions::Status::InvalidParameters, STR_RIDE_CONSTRUCTION_CANT_REMOVE_THIS);
}
- const rct_preview_track* trackBlock = TrackBlocks[trackType];
+ const auto& ted = GetTrackElementDescriptor(trackType);
+ const rct_preview_track* trackBlock = ted.Block;
trackBlock += tileElement->AsTrack()->GetSequenceIndex();
auto startLoc = _origin;
@@ -150,7 +153,7 @@ GameActions::Result::Ptr TrackRemoveAction::Query() const
money32 cost = 0;
- trackBlock = TrackBlocks[trackType];
+ trackBlock = ted.Block;
for (; trackBlock->index != 255; trackBlock++)
{
rotatedTrack = CoordsXYZ{ CoordsXY{ trackBlock->x, trackBlock->y }.Rotate(startLoc.direction), trackBlock->z };
@@ -200,7 +203,7 @@ GameActions::Result::Ptr TrackRemoveAction::Query() const
return MakeResult(GameActions::Status::Unknown, STR_RIDE_CONSTRUCTION_CANT_REMOVE_THIS);
}
- int32_t entranceDirections = TrackSequenceProperties[trackType][0];
+ int32_t entranceDirections = ted.SequenceProperties[0];
if (entranceDirections & TRACK_SEQUENCE_FLAG_ORIGIN && (tileElement->AsTrack()->GetSequenceIndex() == 0))
{
if (!track_remove_station_element({ mapLoc, _origin.direction }, rideIndex, 0))
@@ -226,7 +229,7 @@ GameActions::Result::Ptr TrackRemoveAction::Query() const
}
money32 price = ride->GetRideTypeDescriptor().BuildCosts.TrackPrice;
- price *= TrackPricing[trackType];
+ price *= ted.Price;
price >>= 16;
price = (price + cost) / 2;
if (ride->lifecycle_flags & RIDE_LIFECYCLE_EVER_BEEN_OPENED)
@@ -305,7 +308,7 @@ GameActions::Result::Ptr TrackRemoveAction::Execute() const
}
ride_id_t rideIndex = tileElement->AsTrack()->GetRideIndex();
- auto trackType = tileElement->AsTrack()->GetTrackType();
+ const auto trackType = tileElement->AsTrack()->GetTrackType();
bool isLiftHill = tileElement->AsTrack()->HasChain();
auto ride = get_ride(rideIndex);
@@ -314,7 +317,8 @@ GameActions::Result::Ptr TrackRemoveAction::Execute() const
log_warning("Ride not found. ride index = %d.", rideIndex);
return MakeResult(GameActions::Status::InvalidParameters, STR_RIDE_CONSTRUCTION_CANT_REMOVE_THIS);
}
- const rct_preview_track* trackBlock = TrackBlocks[trackType];
+ const auto& ted = GetTrackElementDescriptor(trackType);
+ const rct_preview_track* trackBlock = ted.Block;
trackBlock += tileElement->AsTrack()->GetSequenceIndex();
auto startLoc = _origin;
@@ -329,7 +333,7 @@ GameActions::Result::Ptr TrackRemoveAction::Execute() const
res->Position.z = startLoc.z;
money32 cost = 0;
- trackBlock = TrackBlocks[trackType];
+ trackBlock = ted.Block;
for (; trackBlock->index != 255; trackBlock++)
{
rotatedTrackLoc = CoordsXYZ{ CoordsXY{ trackBlock->x, trackBlock->y }.Rotate(startLoc.direction), trackBlock->z };
@@ -374,7 +378,7 @@ GameActions::Result::Ptr TrackRemoveAction::Execute() const
return MakeResult(GameActions::Status::Unknown, STR_RIDE_CONSTRUCTION_CANT_REMOVE_THIS);
}
- int32_t entranceDirections = TrackSequenceProperties[trackType][0];
+ int32_t entranceDirections = ted.SequenceProperties[0];
if (entranceDirections & TRACK_SEQUENCE_FLAG_ORIGIN && (tileElement->AsTrack()->GetSequenceIndex() == 0))
{
if (!track_remove_station_element({ mapLoc, _origin.direction }, rideIndex, 0))
@@ -473,7 +477,7 @@ GameActions::Result::Ptr TrackRemoveAction::Execute() const
}
money32 price = ride->GetRideTypeDescriptor().BuildCosts.TrackPrice;
- price *= TrackPricing[trackType];
+ price *= ted.Price;
price >>= 16;
price = (price + cost) / 2;
if (ride->lifecycle_flags & RIDE_LIFECYCLE_EVER_BEEN_OPENED)
diff --git a/src/openrct2/actions/WallPlaceAction.cpp b/src/openrct2/actions/WallPlaceAction.cpp
index 2cce251256..1d2e44916b 100644
--- a/src/openrct2/actions/WallPlaceAction.cpp
+++ b/src/openrct2/actions/WallPlaceAction.cpp
@@ -20,6 +20,7 @@
#include "../world/Surface.h"
#include "../world/Wall.h"
+using namespace OpenRCT2::TrackMetaData;
WallPlaceActionResult::WallPlaceActionResult()
: GameActions::Result(GameActions::Status::Ok, STR_CANT_BUILD_THIS_HERE)
{
@@ -402,6 +403,9 @@ bool WallPlaceAction::WallCheckObstructionWithTrack(
WallSceneryEntry* wall, int32_t z0, TrackElement* trackElement, bool* wallAcrossTrack) const
{
track_type_t trackType = trackElement->GetTrackType();
+
+ using namespace OpenRCT2::TrackMetaData;
+ const auto& ted = GetTrackElementDescriptor(trackType);
int32_t sequence = trackElement->GetSequenceIndex();
int32_t direction = (_edge - trackElement->GetDirection()) & TILE_ELEMENT_DIRECTION_MASK;
auto ride = get_ride(trackElement->GetRideIndex());
@@ -434,20 +438,20 @@ bool WallPlaceAction::WallCheckObstructionWithTrack(
int32_t z;
if (sequence == 0)
{
- if (TrackSequenceProperties[trackType][0] & TRACK_SEQUENCE_FLAG_DISALLOW_DOORS)
+ if (ted.SequenceProperties[0] & TRACK_SEQUENCE_FLAG_DISALLOW_DOORS)
{
return false;
}
if (TrackDefinitions[trackType].bank_start == 0)
{
- if (!(TrackCoordinates[trackType].rotation_begin & 4))
+ if (!(ted.Coordinates.rotation_begin & 4))
{
direction = direction_reverse(trackElement->GetDirection());
if (direction == _edge)
{
- const rct_preview_track* trackBlock = &TrackBlocks[trackType][sequence];
- z = TrackCoordinates[trackType].z_begin;
+ const rct_preview_track* trackBlock = &ted.Block[sequence];
+ z = ted.Coordinates.z_begin;
z = trackElement->base_height + ((z - trackBlock->z) * 8);
if (z == z0)
{
@@ -458,7 +462,7 @@ bool WallPlaceAction::WallCheckObstructionWithTrack(
}
}
- const rct_preview_track* trackBlock = &TrackBlocks[trackType][sequence + 1];
+ const rct_preview_track* trackBlock = &ted.Block[sequence + 1];
if (trackBlock->index != 0xFF)
{
return false;
@@ -469,20 +473,20 @@ bool WallPlaceAction::WallCheckObstructionWithTrack(
return false;
}
- direction = TrackCoordinates[trackType].rotation_end;
+ direction = ted.Coordinates.rotation_end;
if (direction & 4)
{
return false;
}
- direction = (trackElement->GetDirection() + TrackCoordinates[trackType].rotation_end) & TILE_ELEMENT_DIRECTION_MASK;
+ direction = (trackElement->GetDirection() + ted.Coordinates.rotation_end) & TILE_ELEMENT_DIRECTION_MASK;
if (direction != _edge)
{
return false;
}
- trackBlock = &TrackBlocks[trackType][sequence];
- z = TrackCoordinates[trackType].z_end;
+ trackBlock = &ted.Block[sequence];
+ z = ted.Coordinates.z_end;
z = trackElement->base_height + ((z - trackBlock->z) * 8);
return z == z0;
}
@@ -586,7 +590,8 @@ bool WallPlaceAction::TrackIsAllowedWallEdges(
{
if (!GetRideTypeDescriptor(rideType).HasFlag(RIDE_TYPE_FLAG_TRACK_NO_WALLS))
{
- if (TrackSequenceElementAllowedWallEdges[trackType][trackSequence] & (1 << direction))
+ const auto& ted = GetTrackElementDescriptor(trackType);
+ if (ted.SequenceElementAllowedWallEdges[trackSequence] & (1 << direction))
{
return true;
}
diff --git a/src/openrct2/core/DataSerialiserTraits.h b/src/openrct2/core/DataSerialiserTraits.h
index 6de1c5a111..07ae19b21f 100644
--- a/src/openrct2/core/DataSerialiserTraits.h
+++ b/src/openrct2/core/DataSerialiserTraits.h
@@ -817,28 +817,28 @@ template<> struct DataSerializerTraits_t
}
};
-template<> struct DataSerializerTraits_t
+template<> struct DataSerializerTraits_t
{
- static void encode(OpenRCT2::IStream* stream, const rct_peep_thought& val)
+ static void encode(OpenRCT2::IStream* stream, const PeepThought& val)
{
stream->Write(&val.type);
- stream->Write(&val.argument);
+ stream->Write(&val.item);
stream->Write(&val.freshness);
stream->Write(&val.fresh_timeout);
}
- static void decode(OpenRCT2::IStream* stream, rct_peep_thought& val)
+ static void decode(OpenRCT2::IStream* stream, PeepThought& val)
{
stream->Read(&val.type);
- stream->Read(&val.argument);
+ stream->Read(&val.item);
stream->Read(&val.freshness);
stream->Read(&val.fresh_timeout);
}
- static void log(OpenRCT2::IStream* stream, const rct_peep_thought& val)
+ static void log(OpenRCT2::IStream* stream, const PeepThought& val)
{
char msg[128] = {};
snprintf(
- msg, sizeof(msg), "rct_peep_thought(type = %d, item = %u, freshness = %d, freshtimeout = %d)",
- static_cast(val.type), val.argument, val.freshness, val.fresh_timeout);
+ msg, sizeof(msg), "PeepThought(type = %d, item = %u, freshness = %d, freshtimeout = %d)",
+ static_cast(val.type), val.item, val.freshness, val.fresh_timeout);
stream->Write(msg, strlen(msg));
}
};
diff --git a/src/openrct2/libopenrct2.vcxproj b/src/openrct2/libopenrct2.vcxproj
index a989cc7312..ce68dd142e 100644
--- a/src/openrct2/libopenrct2.vcxproj
+++ b/src/openrct2/libopenrct2.vcxproj
@@ -440,6 +440,7 @@
+
@@ -923,4 +924,4 @@
-
\ No newline at end of file
+
diff --git a/src/openrct2/network/NetworkBase.cpp b/src/openrct2/network/NetworkBase.cpp
index d8c3ff70b1..2f4d2c35d9 100644
--- a/src/openrct2/network/NetworkBase.cpp
+++ b/src/openrct2/network/NetworkBase.cpp
@@ -40,7 +40,7 @@
// This string specifies which version of network stream current build uses.
// It is used for making sure only compatible builds get connected, even within
// single OpenRCT2 version.
-#define NETWORK_STREAM_VERSION "6"
+#define NETWORK_STREAM_VERSION "7"
#define NETWORK_STREAM_ID OPENRCT2_VERSION "-" NETWORK_STREAM_VERSION
static Peep* _pickup_peep = nullptr;
@@ -107,9 +107,8 @@ static void network_get_keys_directory(utf8* buffer, size_t bufferSize);
static void network_get_private_key_path(utf8* buffer, size_t bufferSize, const std::string& playerName);
static void network_get_public_key_path(utf8* buffer, size_t bufferSize, const std::string& playerName, const utf8* hash);
-static NetworkBase gNetwork;
-
-NetworkBase::NetworkBase()
+NetworkBase::NetworkBase(OpenRCT2::IContext& context)
+ : OpenRCT2::System(context)
{
wsa_initialized = false;
mode = NETWORK_MODE_NONE;
@@ -150,11 +149,6 @@ NetworkBase::NetworkBase()
_server_log_fs << std::unitbuf;
}
-void NetworkBase::SetEnvironment(const std::shared_ptr& env)
-{
- _env = env;
-}
-
bool NetworkBase::Init()
{
status = NETWORK_STATUS_READY;
@@ -563,7 +557,7 @@ void NetworkBase::UpdateClient()
auto intent = Intent(WC_NETWORK_STATUS);
intent.putExtra(INTENT_EXTRA_MESSAGE, std::string{ str_resolving });
- intent.putExtra(INTENT_EXTRA_CALLBACK, []() -> void { gNetwork.Close(); });
+ intent.putExtra(INTENT_EXTRA_CALLBACK, []() -> void { ::GetContext()->GetNetwork().Close(); });
context_open_intent(&intent);
}
break;
@@ -578,7 +572,7 @@ void NetworkBase::UpdateClient()
auto intent = Intent(WC_NETWORK_STATUS);
intent.putExtra(INTENT_EXTRA_MESSAGE, std::string{ str_connecting });
- intent.putExtra(INTENT_EXTRA_CALLBACK, []() -> void { gNetwork.Close(); });
+ intent.putExtra(INTENT_EXTRA_CALLBACK, []() -> void { ::GetContext()->GetNetwork().Close(); });
context_open_intent(&intent);
server_connect_time = platform_get_ticks();
@@ -595,7 +589,7 @@ void NetworkBase::UpdateClient()
auto intent = Intent(WC_NETWORK_STATUS);
intent.putExtra(INTENT_EXTRA_MESSAGE, std::string{ str_authenticating });
- intent.putExtra(INTENT_EXTRA_CALLBACK, []() -> void { gNetwork.Close(); });
+ intent.putExtra(INTENT_EXTRA_CALLBACK, []() -> void { ::GetContext()->GetNetwork().Close(); });
context_open_intent(&intent);
break;
}
@@ -1104,7 +1098,8 @@ void NetworkBase::AppendLog(std::ostream& fs, std::string_view s)
void NetworkBase::BeginChatLog()
{
- auto directory = _env->GetDirectoryPath(DIRBASE::USER, DIRID::LOG_CHAT);
+ auto env = GetContext().GetPlatformEnvironment();
+ auto directory = env->GetDirectoryPath(DIRBASE::USER, DIRID::LOG_CHAT);
_chatLogPath = BeginLog(directory, "", _chatLogFilenameFormat);
# if defined(_WIN32) && !defined(__MINGW32__)
@@ -1130,7 +1125,8 @@ void NetworkBase::CloseChatLog()
void NetworkBase::BeginServerLog()
{
- auto directory = _env->GetDirectoryPath(DIRBASE::USER, DIRID::LOG_SERVER);
+ auto env = GetContext().GetPlatformEnvironment();
+ auto directory = env->GetDirectoryPath(DIRBASE::USER, DIRID::LOG_SERVER);
_serverLogPath = BeginLog(directory, ServerName, _serverLogFilenameFormat);
# if defined(_WIN32) && !defined(__MINGW32__)
@@ -1297,14 +1293,14 @@ void NetworkBase::Server_Send_OBJECTS_LIST(
}
}
-void NetworkBase::Server_Send_SCRIPTS(NetworkConnection& connection) const
+void NetworkBase::Server_Send_SCRIPTS(NetworkConnection& connection)
{
NetworkPacket packet(NetworkCommand::Scripts);
# ifdef ENABLE_SCRIPTING
using namespace OpenRCT2::Scripting;
- auto& scriptEngine = GetContext()->GetScriptEngine();
+ auto& scriptEngine = GetContext().GetScriptEngine();
const auto& plugins = scriptEngine.GetPlugins();
std::vector> pluginsToSend;
for (const auto& plugin : plugins)
@@ -1393,8 +1389,8 @@ void NetworkBase::Server_Send_MAP(NetworkConnection* connection)
{
// This will send all custom objects to connected clients
// TODO: fix it so custom objects negotiation is performed even in this case.
- auto context = GetContext();
- auto& objManager = context->GetObjectManager();
+ auto& context = GetContext();
+ auto& objManager = context.GetObjectManager();
objects = objManager.GetPackableObjects();
}
@@ -1994,7 +1990,7 @@ void NetworkBase::ServerClientDisconnected(std::unique_ptr& c
network_get_current_player_id() };
auto res = GameActions::Execute(&pickupAction);
}
- gNetwork.Server_Send_EVENT_PLAYER_DISCONNECTED(
+ Server_Send_EVENT_PLAYER_DISCONNECTED(
const_cast(connection_player->Name.c_str()), connection->GetLastDisconnectReason());
// Log player disconnected event
@@ -2188,7 +2184,7 @@ void NetworkBase::Server_Handle_REQUEST_GAMESTATE(NetworkConnection& connection,
return;
}
- IGameStateSnapshots* snapshots = GetContext()->GetGameStateSnapshots();
+ IGameStateSnapshots* snapshots = GetContext().GetGameStateSnapshots();
const GameStateSnapshot_t* snapshot = snapshots->GetLinkedSnapshot(tick);
if (snapshot)
@@ -2284,8 +2280,8 @@ void NetworkBase::Server_Client_Joined(std::string_view name, const std::string&
format_string(text, 256, STR_MULTIPLAYER_PLAYER_HAS_JOINED_THE_GAME, &player_name);
chat_history_add(text);
- auto context = GetContext();
- auto& objManager = context->GetObjectManager();
+ auto& context = GetContext();
+ auto& objManager = context.GetObjectManager();
auto objects = objManager.GetPackableObjects();
Server_Send_OBJECTS_LIST(connection, objects);
Server_Send_SCRIPTS(connection);
@@ -2313,7 +2309,7 @@ void NetworkBase::Server_Handle_TOKEN(NetworkConnection& connection, [[maybe_unu
void NetworkBase::Client_Handle_OBJECTS_LIST(NetworkConnection& connection, NetworkPacket& packet)
{
- auto& repo = GetContext()->GetObjectRepository();
+ auto& repo = GetContext().GetObjectRepository();
uint32_t index = 0;
uint32_t totalObjects = 0;
@@ -2344,7 +2340,7 @@ void NetworkBase::Client_Handle_OBJECTS_LIST(NetworkConnection& connection, Netw
auto intent = Intent(WC_NETWORK_STATUS);
intent.putExtra(INTENT_EXTRA_MESSAGE, std::string{ objectListMsg });
- intent.putExtra(INTENT_EXTRA_CALLBACK, []() -> void { gNetwork.Close(); });
+ intent.putExtra(INTENT_EXTRA_CALLBACK, []() -> void { ::GetContext()->GetNetwork().Close(); });
context_open_intent(&intent);
uint8_t objectType{};
@@ -2403,7 +2399,7 @@ void NetworkBase::Client_Handle_SCRIPTS(NetworkConnection& connection, NetworkPa
packet >> numScripts;
# ifdef ENABLE_SCRIPTING
- auto& scriptEngine = GetContext()->GetScriptEngine();
+ auto& scriptEngine = GetContext().GetScriptEngine();
for (uint32_t i = 0; i < numScripts; i++)
{
uint32_t codeLength{};
@@ -2449,7 +2445,7 @@ void NetworkBase::Client_Handle_GAMESTATE(NetworkConnection& connection, Network
_serverGameState.SetPosition(0);
DataSerialiser ds(false, _serverGameState);
- IGameStateSnapshots* snapshots = GetContext()->GetGameStateSnapshots();
+ IGameStateSnapshots* snapshots = GetContext().GetGameStateSnapshots();
GameStateSnapshot_t& serverSnapshot = snapshots->CreateSnapshot();
snapshots->SerialiseSnapshot(serverSnapshot, ds);
@@ -2459,8 +2455,7 @@ void NetworkBase::Client_Handle_GAMESTATE(NetworkConnection& connection, Network
{
GameStateCompareData_t cmpData = snapshots->Compare(serverSnapshot, *desyncSnapshot);
- std::string outputPath = GetContext()->GetPlatformEnvironment()->GetDirectoryPath(
- DIRBASE::USER, DIRID::LOG_DESYNCS);
+ std::string outputPath = GetContext().GetPlatformEnvironment()->GetDirectoryPath(DIRBASE::USER, DIRID::LOG_DESYNCS);
platform_ensure_directory_exists(outputPath.c_str());
@@ -2508,7 +2503,7 @@ void NetworkBase::Server_Handle_MAPREQUEST(NetworkConnection& connection, Networ
return;
}
log_verbose("Client requested %u objects", size);
- auto& repo = GetContext()->GetObjectRepository();
+ auto& repo = GetContext().GetObjectRepository();
for (uint32_t i = 0; i < size; i++)
{
const char* name = reinterpret_cast(packet.Read(8));
@@ -2703,7 +2698,7 @@ void NetworkBase::Client_Handle_MAP([[maybe_unused]] NetworkConnection& connecti
auto intent = Intent(WC_NETWORK_STATUS);
intent.putExtra(INTENT_EXTRA_MESSAGE, std::string{ str_downloading_map });
- intent.putExtra(INTENT_EXTRA_CALLBACK, []() -> void { gNetwork.Close(); });
+ intent.putExtra(INTENT_EXTRA_CALLBACK, []() -> void { ::GetContext()->GetNetwork().Close(); });
context_open_intent(&intent);
std::memcpy(&chunk_buffer[offset], const_cast(static_cast(packet.Read(chunksize))), chunksize);
@@ -2756,9 +2751,9 @@ bool NetworkBase::LoadMap(IStream* stream)
bool result = false;
try
{
- auto context = GetContext();
- auto& objManager = context->GetObjectManager();
- auto importer = ParkImporter::CreateParkFile(context->GetObjectRepository());
+ auto& context = GetContext();
+ auto& objManager = context.GetObjectManager();
+ auto importer = ParkImporter::CreateParkFile(context.GetObjectRepository());
auto loadResult = importer->LoadFromStream(stream, false);
objManager.LoadObjects(loadResult.RequiredObjects);
importer->Import();
@@ -3173,139 +3168,135 @@ void NetworkBase::Client_Handle_GAMEINFO([[maybe_unused]] NetworkConnection& con
network_chat_show_server_greeting();
}
-void network_set_env(const std::shared_ptr& env)
-{
- gNetwork.SetEnvironment(env);
-}
-
-void network_close()
-{
- gNetwork.Close();
-}
-
void network_reconnect()
{
- gNetwork.Reconnect();
+ OpenRCT2::GetContext()->GetNetwork().Reconnect();
}
void network_shutdown_client()
{
- gNetwork.ServerClientDisconnected();
+ OpenRCT2::GetContext()->GetNetwork().ServerClientDisconnected();
}
int32_t network_begin_client(const std::string& host, int32_t port)
{
- return gNetwork.BeginClient(host, port);
+ return OpenRCT2::GetContext()->GetNetwork().BeginClient(host, port);
}
int32_t network_begin_server(int32_t port, const std::string& address)
{
- return gNetwork.BeginServer(port, address);
+ return OpenRCT2::GetContext()->GetNetwork().BeginServer(port, address);
}
void network_update()
{
- gNetwork.Update();
+ OpenRCT2::GetContext()->GetNetwork().Update();
}
void network_process_pending()
{
- gNetwork.ProcessPending();
+ OpenRCT2::GetContext()->GetNetwork().ProcessPending();
}
void network_flush()
{
- gNetwork.Flush();
+ OpenRCT2::GetContext()->GetNetwork().Flush();
}
int32_t network_get_mode()
{
- return gNetwork.GetMode();
+ return OpenRCT2::GetContext()->GetNetwork().GetMode();
}
int32_t network_get_status()
{
- return gNetwork.GetStatus();
+ return OpenRCT2::GetContext()->GetNetwork().GetStatus();
}
bool network_is_desynchronised()
{
- return gNetwork.IsDesynchronised();
+ return OpenRCT2::GetContext()->GetNetwork().IsDesynchronised();
}
bool network_check_desynchronisation()
{
- return gNetwork.CheckDesynchronizaton();
+ return OpenRCT2::GetContext()->GetNetwork().CheckDesynchronizaton();
}
void network_request_gamestate_snapshot()
{
- return gNetwork.RequestStateSnapshot();
+ return OpenRCT2::GetContext()->GetNetwork().RequestStateSnapshot();
}
void network_send_tick()
{
- gNetwork.Server_Send_TICK();
+ OpenRCT2::GetContext()->GetNetwork().Server_Send_TICK();
}
NetworkAuth network_get_authstatus()
{
- return gNetwork.GetAuthStatus();
+ return OpenRCT2::GetContext()->GetNetwork().GetAuthStatus();
}
uint32_t network_get_server_tick()
{
- return gNetwork.GetServerTick();
+ return OpenRCT2::GetContext()->GetNetwork().GetServerTick();
}
uint8_t network_get_current_player_id()
{
- return gNetwork.GetPlayerID();
+ return OpenRCT2::GetContext()->GetNetwork().GetPlayerID();
}
int32_t network_get_num_players()
{
- return static_cast(gNetwork.player_list.size());
+ return static_cast(OpenRCT2::GetContext()->GetNetwork().player_list.size());
}
const char* network_get_player_name(uint32_t index)
{
- Guard::IndexInRange(index, gNetwork.player_list);
+ auto& network = OpenRCT2::GetContext()->GetNetwork();
+ Guard::IndexInRange(index, network.player_list);
- return static_cast(gNetwork.player_list[index]->Name.c_str());
+ return static_cast(network.player_list[index]->Name.c_str());
}
uint32_t network_get_player_flags(uint32_t index)
{
- Guard::IndexInRange(index, gNetwork.player_list);
+ auto& network = OpenRCT2::GetContext()->GetNetwork();
+ Guard::IndexInRange(index, network.player_list);
- return gNetwork.player_list[index]->Flags;
+ return network.player_list[index]->Flags;
}
int32_t network_get_player_ping(uint32_t index)
{
- Guard::IndexInRange(index, gNetwork.player_list);
+ auto& network = OpenRCT2::GetContext()->GetNetwork();
+ Guard::IndexInRange(index, network.player_list);
- return gNetwork.player_list[index]->Ping;
+ return network.player_list[index]->Ping;
}
int32_t network_get_player_id(uint32_t index)
{
- Guard::IndexInRange(index, gNetwork.player_list);
+ auto& network = OpenRCT2::GetContext()->GetNetwork();
+ Guard::IndexInRange(index, network.player_list);
- return gNetwork.player_list[index]->Id;
+ return network.player_list[index]->Id;
}
money32 network_get_player_money_spent(uint32_t index)
{
- Guard::IndexInRange(index, gNetwork.player_list);
+ auto& network = OpenRCT2::GetContext()->GetNetwork();
+ Guard::IndexInRange(index, network.player_list);
- return gNetwork.player_list[index]->MoneySpent;
+ return network.player_list[index]->MoneySpent;
}
std::string network_get_player_ip_address(uint32_t id)
{
- auto conn = gNetwork.GetPlayerConnection(id);
+ auto& network = OpenRCT2::GetContext()->GetNetwork();
+ auto conn = network.GetPlayerConnection(id);
if (conn != nullptr && conn->Socket != nullptr)
{
return conn->Socket->GetIpAddress();
@@ -3315,7 +3306,8 @@ std::string network_get_player_ip_address(uint32_t id)
std::string network_get_player_public_key_hash(uint32_t id)
{
- auto player = gNetwork.GetPlayerByID(id);
+ auto& network = OpenRCT2::GetContext()->GetNetwork();
+ auto player = network.GetPlayerByID(id);
if (player != nullptr)
{
return player->KeyHash;
@@ -3325,104 +3317,117 @@ std::string network_get_player_public_key_hash(uint32_t id)
void network_add_player_money_spent(uint32_t index, money32 cost)
{
- Guard::IndexInRange(index, gNetwork.player_list);
+ auto& network = OpenRCT2::GetContext()->GetNetwork();
+ Guard::IndexInRange(index, network.player_list);
- gNetwork.player_list[index]->AddMoneySpent(cost);
+ network.player_list[index]->AddMoneySpent(cost);
}
int32_t network_get_player_last_action(uint32_t index, int32_t time)
{
- Guard::IndexInRange(index, gNetwork.player_list);
+ auto& network = OpenRCT2::GetContext()->GetNetwork();
+ Guard::IndexInRange(index, network.player_list);
- if (time && platform_get_ticks() > gNetwork.player_list[index]->LastActionTime + time)
+ if (time && platform_get_ticks() > network.player_list[index]->LastActionTime + time)
{
return -999;
}
- return gNetwork.player_list[index]->LastAction;
+ return network.player_list[index]->LastAction;
}
void network_set_player_last_action(uint32_t index, GameCommand command)
{
- Guard::IndexInRange(index, gNetwork.player_list);
+ auto& network = OpenRCT2::GetContext()->GetNetwork();
+ Guard::IndexInRange(index, network.player_list);
- gNetwork.player_list[index]->LastAction = static_cast(NetworkActions::FindCommand(command));
- gNetwork.player_list[index]->LastActionTime = platform_get_ticks();
+ network.player_list[index]->LastAction = static_cast(NetworkActions::FindCommand(command));
+ network.player_list[index]->LastActionTime = platform_get_ticks();
}
CoordsXYZ network_get_player_last_action_coord(uint32_t index)
{
- Guard::IndexInRange(index, gNetwork.player_list);
+ auto& network = OpenRCT2::GetContext()->GetNetwork();
+ Guard::IndexInRange(index, OpenRCT2::GetContext()->GetNetwork().player_list);
- return gNetwork.player_list[index]->LastActionCoord;
+ return network.player_list[index]->LastActionCoord;
}
void network_set_player_last_action_coord(uint32_t index, const CoordsXYZ& coord)
{
- Guard::IndexInRange(index, gNetwork.player_list);
+ auto& network = OpenRCT2::GetContext()->GetNetwork();
+ Guard::IndexInRange(index, network.player_list);
- if (index < gNetwork.player_list.size())
+ if (index < network.player_list.size())
{
- gNetwork.player_list[index]->LastActionCoord = coord;
+ network.player_list[index]->LastActionCoord = coord;
}
}
uint32_t network_get_player_commands_ran(uint32_t index)
{
- Guard::IndexInRange(index, gNetwork.player_list);
+ auto& network = OpenRCT2::GetContext()->GetNetwork();
+ Guard::IndexInRange(index, OpenRCT2::GetContext()->GetNetwork().player_list);
- return gNetwork.player_list[index]->CommandsRan;
+ return network.player_list[index]->CommandsRan;
}
int32_t network_get_player_index(uint32_t id)
{
- auto it = gNetwork.GetPlayerIteratorByID(id);
- if (it == gNetwork.player_list.end())
+ auto& network = OpenRCT2::GetContext()->GetNetwork();
+ auto it = network.GetPlayerIteratorByID(id);
+ if (it == network.player_list.end())
{
return -1;
}
- return static_cast(gNetwork.GetPlayerIteratorByID(id) - gNetwork.player_list.begin());
+ return static_cast(network.GetPlayerIteratorByID(id) - network.player_list.begin());
}
uint8_t network_get_player_group(uint32_t index)
{
- Guard::IndexInRange(index, gNetwork.player_list);
+ auto& network = OpenRCT2::GetContext()->GetNetwork();
+ Guard::IndexInRange(index, network.player_list);
- return gNetwork.player_list[index]->Group;
+ return network.player_list[index]->Group;
}
void network_set_player_group(uint32_t index, uint32_t groupindex)
{
- Guard::IndexInRange(index, gNetwork.player_list);
- Guard::IndexInRange(groupindex, gNetwork.group_list);
+ auto& network = OpenRCT2::GetContext()->GetNetwork();
+ Guard::IndexInRange(index, network.player_list);
+ Guard::IndexInRange(groupindex, network.group_list);
- gNetwork.player_list[index]->Group = gNetwork.group_list[groupindex]->Id;
+ network.player_list[index]->Group = network.group_list[groupindex]->Id;
}
int32_t network_get_group_index(uint8_t id)
{
- auto it = gNetwork.GetGroupIteratorByID(id);
- if (it == gNetwork.group_list.end())
+ auto& network = OpenRCT2::GetContext()->GetNetwork();
+ auto it = network.GetGroupIteratorByID(id);
+ if (it == network.group_list.end())
{
return -1;
}
- return static_cast(gNetwork.GetGroupIteratorByID(id) - gNetwork.group_list.begin());
+ return static_cast(network.GetGroupIteratorByID(id) - network.group_list.begin());
}
uint8_t network_get_group_id(uint32_t index)
{
- Guard::IndexInRange(index, gNetwork.group_list);
+ auto& network = OpenRCT2::GetContext()->GetNetwork();
+ Guard::IndexInRange(index, network.group_list);
- return gNetwork.group_list[index]->Id;
+ return network.group_list[index]->Id;
}
int32_t network_get_num_groups()
{
- return static_cast(gNetwork.group_list.size());
+ auto& network = OpenRCT2::GetContext()->GetNetwork();
+ return static_cast(network.group_list.size());
}
const char* network_get_group_name(uint32_t index)
{
- return gNetwork.group_list[index]->GetName().c_str();
+ auto& network = OpenRCT2::GetContext()->GetNetwork();
+ return network.group_list[index]->GetName().c_str();
}
void network_chat_show_connected_message()
@@ -3456,15 +3461,16 @@ void network_chat_show_server_greeting()
GameActions::Result::Ptr network_set_player_group(
NetworkPlayerId_t actionPlayerId, NetworkPlayerId_t playerId, uint8_t groupId, bool isExecuting)
{
- NetworkPlayer* player = gNetwork.GetPlayerByID(playerId);
+ auto& network = OpenRCT2::GetContext()->GetNetwork();
+ NetworkPlayer* player = network.GetPlayerByID(playerId);
- NetworkGroup* fromgroup = gNetwork.GetGroupByID(actionPlayerId);
+ NetworkGroup* fromgroup = network.GetGroupByID(actionPlayerId);
if (player == nullptr)
{
return std::make_unique(GameActions::Status::InvalidParameters, STR_CANT_DO_THIS);
}
- if (!gNetwork.GetGroupByID(groupId))
+ if (!network.GetGroupByID(groupId))
{
return std::make_unique(GameActions::Status::InvalidParameters, STR_CANT_DO_THIS);
}
@@ -3487,18 +3493,18 @@ GameActions::Result::Ptr network_set_player_group(
if (network_get_mode() == NETWORK_MODE_SERVER)
{
// Add or update saved user
- NetworkUserManager* userManager = &gNetwork._userManager;
- NetworkUser* networkUser = userManager->GetOrAddUser(player->KeyHash);
+ NetworkUserManager& userManager = network._userManager;
+ NetworkUser* networkUser = userManager.GetOrAddUser(player->KeyHash);
networkUser->GroupId = groupId;
networkUser->Name = player->Name;
- userManager->Save();
+ userManager.Save();
}
window_invalidate_by_number(WC_PLAYER, playerId);
// Log set player group event
- NetworkPlayer* game_command_player = gNetwork.GetPlayerByID(actionPlayerId);
- NetworkGroup* new_player_group = gNetwork.GetGroupByID(groupId);
+ NetworkPlayer* game_command_player = network.GetPlayerByID(actionPlayerId);
+ NetworkGroup* new_player_group = network.GetGroupByID(groupId);
char log_msg[256];
const char* args[3] = {
player->Name.c_str(),
@@ -3515,13 +3521,14 @@ GameActions::Result::Ptr network_modify_groups(
NetworkPlayerId_t actionPlayerId, ModifyGroupType type, uint8_t groupId, const std::string& name, uint32_t permissionIndex,
PermissionState permissionState, bool isExecuting)
{
+ auto& network = OpenRCT2::GetContext()->GetNetwork();
switch (type)
{
case ModifyGroupType::AddGroup:
{
if (isExecuting)
{
- NetworkGroup* newgroup = gNetwork.AddGroup();
+ NetworkGroup* newgroup = network.AddGroup();
if (newgroup == nullptr)
{
return std::make_unique(GameActions::Status::Unknown, STR_CANT_DO_THIS);
@@ -3536,7 +3543,7 @@ GameActions::Result::Ptr network_modify_groups(
return std::make_unique(
GameActions::Status::Disallowed, STR_THIS_GROUP_CANNOT_BE_MODIFIED);
}
- for (const auto& it : gNetwork.player_list)
+ for (const auto& it : network.player_list)
{
if ((it.get())->Group == groupId)
{
@@ -3546,7 +3553,7 @@ GameActions::Result::Ptr network_modify_groups(
}
if (isExecuting)
{
- gNetwork.RemoveGroup(groupId);
+ network.RemoveGroup(groupId);
}
}
break;
@@ -3558,11 +3565,11 @@ GameActions::Result::Ptr network_modify_groups(
GameActions::Status::Disallowed, STR_THIS_GROUP_CANNOT_BE_MODIFIED);
}
NetworkGroup* mygroup = nullptr;
- NetworkPlayer* player = gNetwork.GetPlayerByID(actionPlayerId);
+ NetworkPlayer* player = network.GetPlayerByID(actionPlayerId);
auto networkPermission = static_cast(permissionIndex);
if (player != nullptr && permissionState == PermissionState::Toggle)
{
- mygroup = gNetwork.GetGroupByID(player->Group);
+ mygroup = network.GetGroupByID(player->Group);
if (mygroup == nullptr || !mygroup->CanPerformAction(networkPermission))
{
return std::make_unique(
@@ -3571,7 +3578,7 @@ GameActions::Result::Ptr network_modify_groups(
}
if (isExecuting)
{
- NetworkGroup* group = gNetwork.GetGroupByID(groupId);
+ NetworkGroup* group = network.GetGroupByID(groupId);
if (group != nullptr)
{
if (permissionState != PermissionState::Toggle)
@@ -3598,7 +3605,7 @@ GameActions::Result::Ptr network_modify_groups(
break;
case ModifyGroupType::SetName:
{
- NetworkGroup* group = gNetwork.GetGroupByID(groupId);
+ NetworkGroup* group = network.GetGroupByID(groupId);
const char* oldName = group->GetName().c_str();
if (strcmp(oldName, name.c_str()) == 0)
@@ -3629,7 +3636,7 @@ GameActions::Result::Ptr network_modify_groups(
}
if (isExecuting)
{
- gNetwork.SetDefaultGroup(groupId);
+ network.SetDefaultGroup(groupId);
}
}
break;
@@ -3638,14 +3645,15 @@ GameActions::Result::Ptr network_modify_groups(
return std::make_unique(GameActions::Status::InvalidParameters, STR_NONE);
}
- gNetwork.SaveGroups();
+ network.SaveGroups();
return std::make_unique();
}
GameActions::Result::Ptr network_kick_player(NetworkPlayerId_t playerId, bool isExecuting)
{
- NetworkPlayer* player = gNetwork.GetPlayerByID(playerId);
+ auto& network = OpenRCT2::GetContext()->GetNetwork();
+ NetworkPlayer* player = network.GetPlayerByID(playerId);
if (player == nullptr)
{
// Player might be already removed by the PLAYERLIST command, need to refactor non-game commands executing too
@@ -3660,14 +3668,14 @@ GameActions::Result::Ptr network_kick_player(NetworkPlayerId_t playerId, bool is
if (isExecuting)
{
- if (gNetwork.GetMode() == NETWORK_MODE_SERVER)
+ if (network.GetMode() == NETWORK_MODE_SERVER)
{
- gNetwork.KickPlayer(playerId);
+ network.KickPlayer(playerId);
- NetworkUserManager* networkUserManager = &gNetwork._userManager;
- networkUserManager->Load();
- networkUserManager->RemoveUser(player->KeyHash);
- networkUserManager->Save();
+ NetworkUserManager& networkUserManager = network._userManager;
+ networkUserManager.Load();
+ networkUserManager.RemoveUser(player->KeyHash);
+ networkUserManager.Save();
}
}
return std::make_unique();
@@ -3675,7 +3683,8 @@ GameActions::Result::Ptr network_kick_player(NetworkPlayerId_t playerId, bool is
uint8_t network_get_default_group()
{
- return gNetwork.GetDefaultGroup();
+ auto& network = OpenRCT2::GetContext()->GetNetwork();
+ return network.GetDefaultGroup();
}
int32_t network_get_num_actions()
@@ -3697,27 +3706,30 @@ rct_string_id network_get_action_name_string_id(uint32_t index)
int32_t network_can_perform_action(uint32_t groupindex, NetworkPermission index)
{
- Guard::IndexInRange(groupindex, gNetwork.group_list);
+ auto& network = OpenRCT2::GetContext()->GetNetwork();
+ Guard::IndexInRange(groupindex, network.group_list);
- return gNetwork.group_list[groupindex]->CanPerformAction(index);
+ return network.group_list[groupindex]->CanPerformAction(index);
}
int32_t network_can_perform_command(uint32_t groupindex, int32_t index)
{
- Guard::IndexInRange(groupindex, gNetwork.group_list);
+ auto& network = OpenRCT2::GetContext()->GetNetwork();
+ Guard::IndexInRange(groupindex, network.group_list);
- return gNetwork.group_list[groupindex]->CanPerformCommand(static_cast(index)); // TODO
+ return network.group_list[groupindex]->CanPerformCommand(static_cast(index)); // TODO
}
void network_set_pickup_peep(uint8_t playerid, Peep* peep)
{
- if (gNetwork.GetMode() == NETWORK_MODE_NONE)
+ auto& network = OpenRCT2::GetContext()->GetNetwork();
+ if (network.GetMode() == NETWORK_MODE_NONE)
{
_pickup_peep = peep;
}
else
{
- NetworkPlayer* player = gNetwork.GetPlayerByID(playerid);
+ NetworkPlayer* player = network.GetPlayerByID(playerid);
if (player)
{
player->PickupPeep = peep;
@@ -3727,13 +3739,14 @@ void network_set_pickup_peep(uint8_t playerid, Peep* peep)
Peep* network_get_pickup_peep(uint8_t playerid)
{
- if (gNetwork.GetMode() == NETWORK_MODE_NONE)
+ auto& network = OpenRCT2::GetContext()->GetNetwork();
+ if (network.GetMode() == NETWORK_MODE_NONE)
{
return _pickup_peep;
}
else
{
- NetworkPlayer* player = gNetwork.GetPlayerByID(playerid);
+ NetworkPlayer* player = network.GetPlayerByID(playerid);
if (player)
{
return player->PickupPeep;
@@ -3744,13 +3757,14 @@ Peep* network_get_pickup_peep(uint8_t playerid)
void network_set_pickup_peep_old_x(uint8_t playerid, int32_t x)
{
- if (gNetwork.GetMode() == NETWORK_MODE_NONE)
+ auto& network = OpenRCT2::GetContext()->GetNetwork();
+ if (network.GetMode() == NETWORK_MODE_NONE)
{
_pickup_peep_old_x = x;
}
else
{
- NetworkPlayer* player = gNetwork.GetPlayerByID(playerid);
+ NetworkPlayer* player = network.GetPlayerByID(playerid);
if (player)
{
player->PickupPeepOldX = x;
@@ -3760,13 +3774,14 @@ void network_set_pickup_peep_old_x(uint8_t playerid, int32_t x)
int32_t network_get_pickup_peep_old_x(uint8_t playerid)
{
- if (gNetwork.GetMode() == NETWORK_MODE_NONE)
+ auto& network = OpenRCT2::GetContext()->GetNetwork();
+ if (network.GetMode() == NETWORK_MODE_NONE)
{
return _pickup_peep_old_x;
}
else
{
- NetworkPlayer* player = gNetwork.GetPlayerByID(playerid);
+ NetworkPlayer* player = network.GetPlayerByID(playerid);
if (player)
{
return player->PickupPeepOldX;
@@ -3777,7 +3792,8 @@ int32_t network_get_pickup_peep_old_x(uint8_t playerid)
int32_t network_get_current_player_group_index()
{
- NetworkPlayer* player = gNetwork.GetPlayerByID(gNetwork.GetPlayerID());
+ auto& network = OpenRCT2::GetContext()->GetNetwork();
+ NetworkPlayer* player = network.GetPlayerByID(network.GetPlayerID());
if (player)
{
return network_get_group_index(player->Group);
@@ -3785,33 +3801,29 @@ int32_t network_get_current_player_group_index()
return -1;
}
-void network_send_map()
-{
- gNetwork.Server_Send_MAP();
-}
-
void network_send_chat(const char* text, const std::vector& playerIds)
{
- if (gNetwork.GetMode() == NETWORK_MODE_CLIENT)
+ auto& network = OpenRCT2::GetContext()->GetNetwork();
+ if (network.GetMode() == NETWORK_MODE_CLIENT)
{
- gNetwork.Client_Send_CHAT(text);
+ network.Client_Send_CHAT(text);
}
- else if (gNetwork.GetMode() == NETWORK_MODE_SERVER)
+ else if (network.GetMode() == NETWORK_MODE_SERVER)
{
std::string message = text;
- if (ProcessChatMessagePluginHooks(gNetwork.GetPlayerID(), message))
+ if (ProcessChatMessagePluginHooks(network.GetPlayerID(), message))
{
- auto player = gNetwork.GetPlayerByID(gNetwork.GetPlayerID());
+ auto player = network.GetPlayerByID(network.GetPlayerID());
if (player != nullptr)
{
- auto formatted = gNetwork.FormatChat(player, message.c_str());
+ auto formatted = network.FormatChat(player, message.c_str());
if (playerIds.empty()
- || std::find(playerIds.begin(), playerIds.end(), gNetwork.GetPlayerID()) != playerIds.end())
+ || std::find(playerIds.begin(), playerIds.end(), network.GetPlayerID()) != playerIds.end())
{
// Server is one of the recipients
chat_history_add(formatted);
}
- gNetwork.Server_Send_CHAT(formatted, playerIds);
+ network.Server_Send_CHAT(formatted, playerIds);
}
}
}
@@ -3819,19 +3831,21 @@ void network_send_chat(const char* text, const std::vector& playerIds)
void network_send_game_action(const GameAction* action)
{
- switch (gNetwork.GetMode())
+ auto& network = OpenRCT2::GetContext()->GetNetwork();
+ switch (network.GetMode())
{
case NETWORK_MODE_SERVER:
- gNetwork.Server_Send_GAME_ACTION(action);
+ network.Server_Send_GAME_ACTION(action);
break;
case NETWORK_MODE_CLIENT:
- gNetwork.Client_Send_GAME_ACTION(action);
+ network.Client_Send_GAME_ACTION(action);
break;
}
}
void network_send_password(const std::string& password)
{
+ auto& network = OpenRCT2::GetContext()->GetNetwork();
utf8 keyPath[MAX_PATH];
network_get_private_key_path(keyPath, sizeof(keyPath), gConfigNetwork.player_name);
if (!Platform::FileExists(keyPath))
@@ -3842,36 +3856,39 @@ void network_send_password(const std::string& password)
try
{
auto fs = FileStream(keyPath, FILE_MODE_OPEN);
- gNetwork._key.LoadPrivate(&fs);
+ network._key.LoadPrivate(&fs);
}
catch (const std::exception&)
{
log_error("Error reading private key from %s.", keyPath);
return;
}
- const std::string pubkey = gNetwork._key.PublicKeyString();
+ const std::string pubkey = network._key.PublicKeyString();
std::vector signature;
- gNetwork._key.Sign(gNetwork._challenge.data(), gNetwork._challenge.size(), signature);
+ network._key.Sign(network._challenge.data(), network._challenge.size(), signature);
// Don't keep private key in memory. There's no need and it may get leaked
// when process dump gets collected at some point in future.
- gNetwork._key.Unload();
- gNetwork.Client_Send_AUTH(gConfigNetwork.player_name.c_str(), password, pubkey.c_str(), signature);
+ network._key.Unload();
+ network.Client_Send_AUTH(gConfigNetwork.player_name.c_str(), password, pubkey.c_str(), signature);
}
void network_set_password(const char* password)
{
- gNetwork.SetPassword(password);
+ auto& network = OpenRCT2::GetContext()->GetNetwork();
+ network.SetPassword(password);
}
void network_append_chat_log(std::string_view text)
{
- gNetwork.AppendChatLog(text);
+ auto& network = OpenRCT2::GetContext()->GetNetwork();
+ network.AppendChatLog(text);
}
void network_append_server_log(const utf8* text)
{
- gNetwork.AppendServerLog(text);
+ auto& network = OpenRCT2::GetContext()->GetNetwork();
+ network.AppendServerLog(text);
}
static void network_get_keys_directory(utf8* buffer, size_t bufferSize)
@@ -3897,27 +3914,33 @@ static void network_get_public_key_path(utf8* buffer, size_t bufferSize, const s
const utf8* network_get_server_name()
{
- return gNetwork.ServerName.c_str();
+ auto& network = OpenRCT2::GetContext()->GetNetwork();
+ return network.ServerName.c_str();
}
const utf8* network_get_server_description()
{
- return gNetwork.ServerDescription.c_str();
+ auto& network = OpenRCT2::GetContext()->GetNetwork();
+ return network.ServerDescription.c_str();
}
const utf8* network_get_server_greeting()
{
- return gNetwork.ServerGreeting.c_str();
+ auto& network = OpenRCT2::GetContext()->GetNetwork();
+ return network.ServerGreeting.c_str();
}
const utf8* network_get_server_provider_name()
{
- return gNetwork.ServerProviderName.c_str();
+ auto& network = OpenRCT2::GetContext()->GetNetwork();
+ return network.ServerProviderName.c_str();
}
const utf8* network_get_server_provider_email()
{
- return gNetwork.ServerProviderEmail.c_str();
+ auto& network = OpenRCT2::GetContext()->GetNetwork();
+ return network.ServerProviderEmail.c_str();
}
const utf8* network_get_server_provider_website()
{
- return gNetwork.ServerProviderWebsite.c_str();
+ auto& network = OpenRCT2::GetContext()->GetNetwork();
+ return network.ServerProviderWebsite.c_str();
}
std::string network_get_version()
@@ -3927,12 +3950,14 @@ std::string network_get_version()
NetworkStats_t network_get_stats()
{
- return gNetwork.GetStats();
+ auto& network = OpenRCT2::GetContext()->GetNetwork();
+ return network.GetStats();
}
NetworkServerState_t network_get_server_state()
{
- return gNetwork.GetServerState();
+ auto& network = OpenRCT2::GetContext()->GetNetwork();
+ return network.GetServerState();
}
bool network_gamestate_snapshots_enabled()
@@ -3942,7 +3967,8 @@ bool network_gamestate_snapshots_enabled()
json_t network_get_server_info_as_json()
{
- return gNetwork.GetServerInfoAsJson();
+ auto& network = OpenRCT2::GetContext()->GetNetwork();
+ return network.GetServerInfoAsJson();
}
#else
int32_t network_get_mode()
@@ -3985,9 +4011,6 @@ void network_request_gamestate_snapshot()
void network_send_game_action(const GameAction* action)
{
}
-void network_send_map()
-{
-}
void network_update()
{
}
@@ -4140,15 +4163,9 @@ void network_send_chat(const char* text, const std::vector& playerIds)
void network_send_password(const std::string& password)
{
}
-void network_close()
-{
-}
void network_reconnect()
{
}
-void network_set_env(const std::shared_ptr&)
-{
-}
void network_shutdown_client()
{
}
diff --git a/src/openrct2/network/NetworkBase.h b/src/openrct2/network/NetworkBase.h
index 646a7602d2..79f49f8615 100644
--- a/src/openrct2/network/NetworkBase.h
+++ b/src/openrct2/network/NetworkBase.h
@@ -1,5 +1,6 @@
#pragma once
+#include "../System.hpp"
#include "../actions/GameAction.h"
#include "../object/Object.h"
#include "NetworkConnection.h"
@@ -13,21 +14,26 @@
#ifndef DISABLE_NETWORK
-class NetworkBase
+namespace OpenRCT2
+{
+ struct IContext;
+}
+
+class NetworkBase : public OpenRCT2::System
{
public:
- NetworkBase();
+ NetworkBase(OpenRCT2::IContext& context);
public: // Uncategorized
bool BeginServer(uint16_t port, const std::string& address);
bool BeginClient(const std::string& host, uint16_t port);
public: // Common
- void SetEnvironment(const std::shared_ptr& env);
bool Init();
void Close();
uint32_t GetServerTick();
- void Update();
+ // FIXME: This is currently the wrong function to override in System, will be refactored later.
+ void Update() override final;
void Flush();
void ProcessPending();
void ProcessPlayerList();
@@ -91,7 +97,7 @@ public: // Server
void Server_Send_EVENT_PLAYER_JOINED(const char* playerName);
void Server_Send_EVENT_PLAYER_DISCONNECTED(const char* playerName, const char* reason);
void Server_Send_OBJECTS_LIST(NetworkConnection& connection, const std::vector& objects) const;
- void Server_Send_SCRIPTS(NetworkConnection& connection) const;
+ void Server_Send_SCRIPTS(NetworkConnection& connection);
// Handlers
void Server_Handle_REQUEST_GAMESTATE(NetworkConnection& connection, NetworkPacket& packet);
@@ -174,7 +180,6 @@ public: // Public common
private: // Common Data
using CommandHandler = void (NetworkBase::*)(NetworkConnection& connection, NetworkPacket& packet);
- std::shared_ptr _env;
std::vector chunk_buffer;
std::ofstream _chat_log_fs;
uint32_t _lastUpdateTime = 0;
diff --git a/src/openrct2/network/network.h b/src/openrct2/network/network.h
index 6e5e246fb6..b6b5784cab 100644
--- a/src/openrct2/network/network.h
+++ b/src/openrct2/network/network.h
@@ -36,13 +36,6 @@ enum class ModifyGroupType : uint8_t;
enum class PermissionState : uint8_t;
enum class NetworkPermission : uint32_t;
-namespace OpenRCT2
-{
- struct IPlatformEnvironment;
-}
-
-void network_set_env(const std::shared_ptr& env);
-void network_close();
void network_reconnect();
void network_shutdown_client();
int32_t network_begin_client(const std::string& host, int32_t port);
@@ -100,10 +93,8 @@ void network_set_pickup_peep(uint8_t playerid, Peep* peep);
void network_set_pickup_peep_old_x(uint8_t playerid, int32_t x);
[[nodiscard]] int32_t network_get_pickup_peep_old_x(uint8_t playerid);
-void network_send_map();
void network_send_chat(const char* text, const std::vector& playerIds = {});
void network_send_game_action(const GameAction* action);
-void network_enqueue_game_action(const GameAction* action);
void network_send_password(const std::string& password);
void network_set_password(const char* password);
diff --git a/src/openrct2/object/FootpathObject.cpp b/src/openrct2/object/FootpathObject.cpp
index 6de138b344..827c3527c9 100644
--- a/src/openrct2/object/FootpathObject.cpp
+++ b/src/openrct2/object/FootpathObject.cpp
@@ -42,21 +42,21 @@ void FootpathObject::Load()
_pathSurfaceEntry.string_idx = _legacyType.string_idx;
_pathSurfaceEntry.image = _legacyType.image;
- _pathSurfaceEntry.preview = _legacyType.image + 71;
+ _pathSurfaceEntry.preview = _legacyType.GetPreviewImage();
_pathSurfaceEntry.flags = _legacyType.flags;
_queueEntry.string_idx = _legacyType.string_idx;
- _queueEntry.image = _legacyType.image + 51;
- _queueEntry.preview = _legacyType.image + 72;
+ _queueEntry.image = _legacyType.GetQueueImage();
+ _queueEntry.preview = _legacyType.GetQueuePreviewImage();
_queueEntry.flags = _legacyType.flags | FOOTPATH_ENTRY_FLAG_IS_QUEUE;
_pathRailingsEntry.string_idx = _legacyType.string_idx;
_pathRailingsEntry.bridge_image = _legacyType.bridge_image;
- _pathRailingsEntry.preview = _legacyType.image + 71;
+ _pathRailingsEntry.preview = _legacyType.GetPreviewImage();
_pathRailingsEntry.flags = _legacyType.flags;
_pathRailingsEntry.scrolling_mode = _legacyType.scrolling_mode;
_pathRailingsEntry.support_type = _legacyType.support_type;
- _pathRailingsEntry.railings_image = _legacyType.image + 73;
+ _pathRailingsEntry.railings_image = _legacyType.GetRailingsImage();
}
void FootpathObject::Unload()
diff --git a/src/openrct2/peep/Guest.cpp b/src/openrct2/peep/Guest.cpp
index ed4fd98a9b..aee6754945 100644
--- a/src/openrct2/peep/Guest.cpp
+++ b/src/openrct2/peep/Guest.cpp
@@ -3226,7 +3226,7 @@ void Guest::StopPurchaseThought(uint8_t ride_type)
// Remove the related thought
for (int32_t i = 0; i < PEEP_MAX_THOUGHTS; ++i)
{
- rct_peep_thought* thought = &Thoughts[i];
+ PeepThought* thought = &Thoughts[i];
if (thought->type == PeepThoughtType::None)
break;
@@ -3236,7 +3236,7 @@ void Guest::StopPurchaseThought(uint8_t ride_type)
if (i < PEEP_MAX_THOUGHTS - 1)
{
- memmove(thought, thought + 1, sizeof(rct_peep_thought) * (PEEP_MAX_THOUGHTS - i - 1));
+ memmove(thought, thought + 1, sizeof(PeepThought) * (PEEP_MAX_THOUGHTS - i - 1));
}
Thoughts[PEEP_MAX_THOUGHTS - 1].type = PeepThoughtType::None;
@@ -6768,14 +6768,14 @@ bool Guest::HeadingForRideOrParkExit() const
* argument_1 (esi & ebx)
* argument_2 (esi+2)
*/
-void peep_thought_set_format_args(const rct_peep_thought* thought, Formatter& ft)
+void peep_thought_set_format_args(const PeepThought* thought, Formatter& ft)
{
ft.Add(PeepThoughts[EnumValue(thought->type)]);
PeepThoughtToActionFlag flags = PeepThoughtToActionMap[EnumValue(thought->type)].flags;
if (flags & PEEP_THOUGHT_ACTION_FLAG_RIDE)
{
- auto ride = get_ride(thought->ride);
+ auto ride = get_ride(thought->rideId);
if (ride != nullptr)
{
ride->FormatNameTo(ft);
@@ -6787,30 +6787,32 @@ void peep_thought_set_format_args(const rct_peep_thought* thought, Formatter& ft
}
else if (flags & PEEP_THOUGHT_ACTION_FLAG_SHOP_ITEM_SINGULAR)
{
- ft.Add(GetShopItemDescriptor(thought->item).Naming.Singular);
+ ft.Add(GetShopItemDescriptor(thought->shopItem).Naming.Singular);
}
else if (flags & PEEP_THOUGHT_ACTION_FLAG_SHOP_ITEM_INDEFINITE)
{
- ft.Add(GetShopItemDescriptor(thought->item).Naming.Indefinite);
+ ft.Add(GetShopItemDescriptor(thought->shopItem).Naming.Indefinite);
}
}
-void Guest::InsertNewThought(PeepThoughtType thoughtType)
+void Guest::InsertNewThought(PeepThoughtType thought_type)
{
- InsertNewThought(thoughtType, std::numeric_limits::max());
+ InsertNewThought(thought_type, PeepThoughtItemNone);
}
-void Guest::InsertNewThought(PeepThoughtType thoughtType, ride_id_t ride)
+void Guest::InsertNewThought(PeepThoughtType thought_type, ShopItem shopItem)
{
- InsertNewThought(thoughtType, static_cast(ride));
+ InsertNewThought(thought_type, static_cast(shopItem));
}
-void Guest::InsertNewThought(PeepThoughtType thoughtType, ShopItem item)
-{
- InsertNewThought(thoughtType, static_cast(item));
-}
-
-void Guest::InsertNewThought(PeepThoughtType thoughtType, uint32_t arg)
+/**
+ *
+ * rct2: 0x699F5A
+ * al:thoughtType
+ * ah:thoughtArguments
+ * esi: peep
+ */
+void Guest::InsertNewThought(PeepThoughtType thoughtType, uint16_t thoughtArguments)
{
PeepActionType newAction = PeepThoughtToActionMap[EnumValue(thoughtType)].action;
if (newAction != PeepActionType::Walking && IsActionInterruptable())
@@ -6823,28 +6825,28 @@ void Guest::InsertNewThought(PeepThoughtType thoughtType, uint32_t arg)
for (int32_t i = 0; i < PEEP_MAX_THOUGHTS; ++i)
{
- rct_peep_thought* thought = &Thoughts[i];
+ PeepThought* thought = &Thoughts[i];
// Remove the oldest thought by setting it to NONE.
if (thought->type == PeepThoughtType::None)
break;
- if (thought->type == thoughtType && thought->argument == arg)
+ if (thought->type == thoughtType && thought->item == thoughtArguments)
{
// If the thought type has not changed then we need to move
// it to the top of the thought list. This is done by first removing the
// existing thought and placing it at the top.
if (i < PEEP_MAX_THOUGHTS - 2)
{
- memmove(thought, thought + 1, sizeof(rct_peep_thought) * (PEEP_MAX_THOUGHTS - i - 1));
+ memmove(thought, thought + 1, sizeof(PeepThought) * (PEEP_MAX_THOUGHTS - i - 1));
}
break;
}
}
- memmove(&Thoughts[1], &Thoughts[0], sizeof(rct_peep_thought) * (PEEP_MAX_THOUGHTS - 1));
+ memmove(&Thoughts[1], &Thoughts[0], sizeof(PeepThought) * (PEEP_MAX_THOUGHTS - 1));
Thoughts[0].type = thoughtType;
- Thoughts[0].argument = arg;
+ Thoughts[0].item = thoughtArguments;
Thoughts[0].freshness = 0;
Thoughts[0].fresh_timeout = 0;
@@ -7446,7 +7448,7 @@ void Guest::RemoveRideFromMemory(ride_id_t rideId)
break;
// Ride ids and shop item ids might have the same value, look only for ride thoughts.
- if (IsThoughtShopItemRelated(entry.type) || entry.ride != rideId)
+ if (IsThoughtShopItemRelated(entry.type) || entry.rideId != rideId)
{
it++;
continue;
@@ -7461,6 +7463,6 @@ void Guest::RemoveRideFromMemory(ride_id_t rideId)
// Last slot is now free.
auto& lastEntry = Thoughts.back();
lastEntry.type = PeepThoughtType::None;
- lastEntry.argument = 0;
+ lastEntry.item = PeepThoughtItemNone;
}
}
diff --git a/src/openrct2/peep/Peep.cpp b/src/openrct2/peep/Peep.cpp
index 446a8a6138..34f498903d 100644
--- a/src/openrct2/peep/Peep.cpp
+++ b/src/openrct2/peep/Peep.cpp
@@ -886,8 +886,7 @@ static void peep_update_thoughts(Guest* peep)
// Clear top thought, push others up
if (i < PEEP_MAX_THOUGHTS - 2)
{
- memmove(
- &peep->Thoughts[i], &peep->Thoughts[i + 1], sizeof(rct_peep_thought) * (PEEP_MAX_THOUGHTS - i - 1));
+ memmove(&peep->Thoughts[i], &peep->Thoughts[i + 1], sizeof(PeepThought) * (PEEP_MAX_THOUGHTS - i - 1));
}
peep->Thoughts[PEEP_MAX_THOUGHTS - 1].type = PeepThoughtType::None;
}
diff --git a/src/openrct2/peep/Peep.h b/src/openrct2/peep/Peep.h
index 94d8c80be7..e14094921d 100644
--- a/src/openrct2/peep/Peep.h
+++ b/src/openrct2/peep/Peep.h
@@ -484,17 +484,19 @@ enum PeepRideDecision
PEEP_RIDE_DECISION_THINKING = 1 << 2,
};
-struct rct_peep_thought
+static constexpr uint16_t PeepThoughtItemNone = std::numeric_limits::max();
+
+struct PeepThought
{
PeepThoughtType type;
union
{
- uint32_t argument;
- ride_id_t ride;
- ShopItem item;
+ ride_id_t rideId;
+ ShopItem shopItem;
+ uint16_t item;
};
- uint8_t freshness;
- uint8_t fresh_timeout;
+ uint8_t freshness; // larger is less fresh
+ uint8_t fresh_timeout; // updates every tick
};
struct Guest;
@@ -707,7 +709,7 @@ public:
int8_t RejoinQueueTimeout; // whilst waiting for a free vehicle (or pair) in the entrance
ride_id_t PreviousRide;
uint16_t PreviousRideTimeOut;
- std::array Thoughts;
+ std::array Thoughts;
// 0x3F Litter Count split into lots of 3 with time, 0xC0 Time since last recalc
uint8_t LitterCount;
// 0x3F Sick Count split into lots of 3 with time, 0xC0 Time since last recalc
@@ -770,10 +772,9 @@ public:
void HandleEasterEggName();
int32_t GetEasterEggNameId() const;
void UpdateEasterEggInteractions();
- void InsertNewThought(PeepThoughtType thoughtType);
- void InsertNewThought(PeepThoughtType thoughtType, uint32_t arg);
- void InsertNewThought(PeepThoughtType thoughtType, ride_id_t ride);
- void InsertNewThought(PeepThoughtType thoughtType, ShopItem shopItem);
+ void InsertNewThought(PeepThoughtType thought_type);
+ void InsertNewThought(PeepThoughtType thought_type, ShopItem thought_arguments);
+ void InsertNewThought(PeepThoughtType thought_type, uint16_t thought_arguments);
static Guest* Generate(const CoordsXYZ& coords);
bool UpdateQueuePosition(PeepActionType previous_action);
void RemoveFromQueue();
@@ -1026,7 +1027,7 @@ void peep_stop_crowd_noise();
void peep_update_crowd_noise();
void peep_update_days_in_queue();
void peep_applause();
-void peep_thought_set_format_args(const rct_peep_thought* thought, Formatter& ft);
+void peep_thought_set_format_args(const PeepThought* thought, Formatter& ft);
int32_t get_peep_face_sprite_small(Guest* peep);
int32_t get_peep_face_sprite_large(Guest* peep);
void peep_sprite_remove(Peep* peep);
diff --git a/src/openrct2/rct1/RCT1.h b/src/openrct2/rct1/RCT1.h
index 07fef8d2bc..1340345651 100644
--- a/src/openrct2/rct1/RCT1.h
+++ b/src/openrct2/rct1/RCT1.h
@@ -35,20 +35,20 @@ namespace RCT1
constexpr const uint32_t RCT1_NUM_TERRAIN_EDGES = 15;
#pragma pack(push, 1)
- struct rct1_entrance
+ struct Entrance
{
uint16_t x;
uint16_t y;
uint16_t z;
uint8_t direction;
};
- assert_struct_size(rct1_entrance, 7);
+ assert_struct_size(Entrance, 7);
/**
* RCT1 ride structure
* size: 0x260
*/
- struct rct1_ride
+ struct Ride
{
uint8_t type; // 0x000
uint8_t vehicle_type; // 0x001
@@ -207,9 +207,9 @@ namespace RCT1
uint8_t entrance_style; // 0x179
uint8_t unk_17A[230]; // 0x17A
};
- assert_struct_size(rct1_ride, 0x260);
+ assert_struct_size(Ride, 0x260);
- struct rct1_unk_sprite : RCT12SpriteBase
+ struct UnkEntity : RCT12SpriteBase
{
uint8_t pad_1F[3]; // 0x1f
rct_string_id name_string_idx; // 0x22
@@ -221,7 +221,7 @@ namespace RCT1
uint8_t var_71;
};
- struct rct1_vehicle : RCT12SpriteBase
+ struct Vehicle : RCT12SpriteBase
{
uint8_t Pitch; // 0x1F
uint8_t bank_rotation; // 0x20
@@ -300,8 +300,7 @@ namespace RCT1
uint8_t var_C4;
uint8_t animation_frame;
uint8_t pad_C6[0x2];
- uint16_t animationState;
- uint16_t var_CA;
+ uint32_t animationState;
uint8_t scream_sound_id; // 0xCC
uint8_t TrackSubposition;
union
@@ -333,7 +332,7 @@ namespace RCT1
}
};
- struct rct1_peep : RCT12SpriteBase
+ struct Peep : RCT12SpriteBase
{
uint8_t pad_1F[3];
rct_string_id name_string_idx; // 0x22
@@ -477,7 +476,7 @@ namespace RCT1
return item_standard_flags;
}
};
- assert_struct_size(rct1_peep, 0x100);
+ assert_struct_size(Peep, 0x100);
enum RCT1_PEEP_SPRITE_TYPE
{
@@ -511,12 +510,12 @@ namespace RCT1
RCT1_PEEP_SPRITE_TYPE_TOFFEE_APPLE = 30
};
- union rct1_sprite
+ union Entity
{
uint8_t pad_00[0x100];
- rct1_unk_sprite unknown;
- rct1_vehicle vehicle;
- rct1_peep peep;
+ UnkEntity unknown;
+ Vehicle vehicle;
+ Peep peep;
RCT12SpriteLitter litter;
RCT12SpriteBalloon balloon;
RCT12SpriteDuck duck;
@@ -526,9 +525,9 @@ namespace RCT1
RCT12SpriteCrashSplash crash_splash;
RCT12SpriteSteamParticle steam_particle;
};
- assert_struct_size(rct1_sprite, 0x100);
+ assert_struct_size(Entity, 0x100);
- struct rct1_research_item
+ struct ResearchItem
{
uint8_t item;
uint8_t related_ride;
@@ -536,13 +535,13 @@ namespace RCT1
uint8_t flags;
uint8_t category;
};
- assert_struct_size(rct1_research_item, 5);
+ assert_struct_size(ResearchItem, 5);
/**
* RCT1,AA,LL scenario / saved game structure.
* size: 0x1F850C
*/
- struct rct1_s4
+ struct S4
{
uint16_t month;
uint16_t day;
@@ -551,7 +550,7 @@ namespace RCT1
uint32_t random_b;
RCT12TileElement tile_elements[RCT1_MAX_TILE_ELEMENTS];
uint32_t unk_counter;
- rct1_sprite sprites[RCT1_MAX_SPRITES];
+ Entity sprites[RCT1_MAX_SPRITES];
uint16_t next_sprite_index;
uint16_t first_vehicle_sprite_index;
uint16_t first_peep_sprite_index;
@@ -570,7 +569,7 @@ namespace RCT1
money32 loan;
uint32_t park_flags;
money16 park_entrance_fee;
- rct1_entrance park_entrance;
+ Entrance park_entrance;
uint8_t unk_198849;
rct12_peep_spawn peep_spawn[RCT12_MAX_PEEP_SPAWNS];
uint8_t unk_198856;
@@ -600,7 +599,7 @@ namespace RCT1
uint8_t last_research_ride;
uint8_t last_research_type;
uint8_t last_research_flags;
- rct1_research_item research_items[200];
+ ResearchItem research_items[200];
uint8_t next_research_item;
uint8_t next_research_ride;
uint8_t next_research_type;
@@ -668,12 +667,12 @@ namespace RCT1
uint8_t unk_199C96[3];
uint8_t water_colour;
uint16_t unk_199C9A;
- rct1_research_item research_items_LL[180];
+ ResearchItem research_items_LL[180];
uint8_t unk_19A020[5468];
RCT12Banner banners[RCT1_MAX_BANNERS];
char string_table[RCT12_MAX_USER_STRINGS][RCT12_USER_STRING_MAX_LENGTH];
uint32_t game_time_counter;
- rct1_ride rides[RCT12_MAX_RIDES_IN_PARK];
+ Ride rides[RCT12_MAX_RIDES_IN_PARK];
uint16_t unk_game_time_counter;
int16_t view_x;
int16_t view_y;
@@ -713,13 +712,13 @@ namespace RCT1
uint8_t unk_1F8358[432];
uint32_t expansion_pack_checksum;
};
- assert_struct_size(rct1_s4, 0x1F850C);
+ assert_struct_size(S4, 0x1F850C);
/**
* Track design structure. Only for base RCT1
* size: 0x2006
*/
- struct rct_track_td4
+ struct TD4
{
uint8_t type; // 0x00
uint8_t vehicle_type;
@@ -761,13 +760,13 @@ namespace RCT1
money16 upkeep_cost; // 0x36
};
- assert_struct_size(rct_track_td4, 0x38);
+ assert_struct_size(TD4, 0x38);
/**
* Track design structure for Added Attractions / Loopy Landscapes
* size: 0x2006
*/
- struct rct_track_td4_aa : public rct_track_td4
+ struct TD4AA : public TD4
{
uint8_t track_spine_colour[RCT12_NUM_COLOUR_SCHEMES]; // 0x38
uint8_t track_rail_colour[RCT12_NUM_COLOUR_SCHEMES]; // 0x3C
@@ -777,7 +776,7 @@ namespace RCT1
uint8_t pad_45[0x7F]; // 0x45
};
- assert_struct_size(rct_track_td4_aa, 0xC4);
+ assert_struct_size(TD4AA, 0xC4);
#pragma pack(pop)
enum
diff --git a/src/openrct2/rct1/S4Importer.cpp b/src/openrct2/rct1/S4Importer.cpp
index 9bb0c107d2..4dea0e59fa 100644
--- a/src/openrct2/rct1/S4Importer.cpp
+++ b/src/openrct2/rct1/S4Importer.cpp
@@ -119,7 +119,7 @@ namespace RCT1
{
private:
std::string _s4Path;
- rct1_s4 _s4 = {};
+ S4 _s4 = {};
uint8_t _gameVersion = 0;
uint8_t _parkValueConversionFactor = 0;
bool _isScenario = false;
@@ -323,27 +323,27 @@ namespace RCT1
}
private:
- std::unique_ptr ReadAndDecodeS4(IStream* stream, bool isScenario)
+ std::unique_ptr ReadAndDecodeS4(IStream* stream, bool isScenario)
{
- auto s4 = std::make_unique();
+ auto s4 = std::make_unique();
size_t dataSize = stream->GetLength() - stream->GetPosition();
auto data = stream->ReadArray(dataSize);
- auto decodedData = std::make_unique(sizeof(rct1_s4));
+ auto decodedData = std::make_unique(sizeof(S4));
size_t decodedSize;
int32_t fileType = sawyercoding_detect_file_type(data.get(), dataSize);
if (isScenario && (fileType & FILE_VERSION_MASK) != FILE_VERSION_RCT1)
{
- decodedSize = sawyercoding_decode_sc4(data.get(), decodedData.get(), dataSize, sizeof(rct1_s4));
+ decodedSize = sawyercoding_decode_sc4(data.get(), decodedData.get(), dataSize, sizeof(S4));
}
else
{
- decodedSize = sawyercoding_decode_sv4(data.get(), decodedData.get(), dataSize, sizeof(rct1_s4));
+ decodedSize = sawyercoding_decode_sv4(data.get(), decodedData.get(), dataSize, sizeof(S4));
}
- if (decodedSize == sizeof(rct1_s4))
+ if (decodedSize == sizeof(S4))
{
- std::memcpy(s4.get(), decodedData.get(), sizeof(rct1_s4));
+ std::memcpy(s4.get(), decodedData.get(), sizeof(S4));
return s4;
}
else
@@ -461,12 +461,12 @@ namespace RCT1
void AddAvailableEntriesFromResearchList()
{
size_t researchListCount;
- const rct1_research_item* researchList = GetResearchList(&researchListCount);
+ const ResearchItem* researchList = GetResearchList(&researchListCount);
std::bitset rideTypeInResearch = GetRideTypesPresentInResearchList(
researchList, researchListCount);
for (size_t i = 0; i < researchListCount; i++)
{
- const rct1_research_item* researchItem = &researchList[i];
+ const ResearchItem* researchItem = &researchList[i];
if (researchItem->flags == RCT1_RESEARCH_FLAGS_SEPARATOR)
{
@@ -815,7 +815,7 @@ namespace RCT1
}
}
- void ImportRide(Ride* dst, rct1_ride* src, ride_id_t rideIndex)
+ void ImportRide(::Ride* dst, RCT1::Ride* src, ride_id_t rideIndex)
{
*dst = {};
dst->id = rideIndex;
@@ -1090,7 +1090,7 @@ namespace RCT1
dst->music_tune_id = 255;
}
- void SetRideColourScheme(Ride* dst, rct1_ride* src)
+ void SetRideColourScheme(::Ride* dst, RCT1::Ride* src)
{
// Colours
dst->colour_scheme_type = src->colour_scheme;
@@ -1145,8 +1145,7 @@ namespace RCT1
for (int i = 0; i < RCT1_MAX_TRAINS_PER_RIDE; i++)
{
// RCT1 had no third colour
- RCT1::RCT1VehicleColourSchemeCopyDescriptor colourSchemeCopyDescriptor = RCT1::
- GetColourSchemeCopyDescriptor(src->vehicle_type);
+ const auto colourSchemeCopyDescriptor = GetColourSchemeCopyDescriptor(src->vehicle_type);
if (colourSchemeCopyDescriptor.colour1 == COPY_COLOUR_1)
{
dst->vehicle_colours[i].Body = RCT1::GetColour(src->vehicle_colours[i].body);
@@ -1243,11 +1242,11 @@ namespace RCT1
}
}
- void SetVehicleColours(Vehicle* dst, const rct1_vehicle* src)
+ void SetVehicleColours(::Vehicle* dst, const RCT1::Vehicle* src)
{
- rct1_ride* srcRide = &_s4.rides[src->ride];
- uint8_t vehicleTypeIndex = srcRide->vehicle_type;
- RCT1::RCT1VehicleColourSchemeCopyDescriptor colourSchemeCopyDescriptor = RCT1::GetColourSchemeCopyDescriptor(
+ const auto& srcRide = _s4.rides[src->ride];
+ uint8_t vehicleTypeIndex = srcRide.vehicle_type;
+ RCT1::VehicleColourSchemeCopyDescriptor colourSchemeCopyDescriptor = RCT1::GetColourSchemeCopyDescriptor(
vehicleTypeIndex);
// RCT1 had no third colour
@@ -1291,7 +1290,7 @@ namespace RCT1
}
}
- void ImportPeep(Peep* dst, const rct1_peep* src)
+ void ImportPeep(::Peep* dst, const RCT1::Peep* src)
{
// Peep vs. staff (including which kind)
dst->SpriteType = RCT1::GetPeepSpriteType(src->sprite_type);
@@ -1881,7 +1880,7 @@ namespace RCT1
research_reset_items();
size_t researchListCount;
- const rct1_research_item* researchList = GetResearchList(&researchListCount);
+ const RCT1::ResearchItem* researchList = GetResearchList(&researchListCount);
// Initialise the "seen" tables
_researchRideEntryUsed.reset();
@@ -1896,29 +1895,29 @@ namespace RCT1
bool researched = true;
std::bitset rideTypeInResearch = GetRideTypesPresentInResearchList(
researchList, researchListCount);
- std::vector vehiclesWithMissingRideTypes;
+ std::vector vehiclesWithMissingRideTypes;
for (size_t i = 0; i < researchListCount; i++)
{
- const rct1_research_item* researchItem = &researchList[i];
- if (researchItem->flags == RCT1_RESEARCH_FLAGS_SEPARATOR)
+ const auto& researchItem = researchList[i];
+ if (researchItem.flags == RCT1_RESEARCH_FLAGS_SEPARATOR)
{
- if (researchItem->item == RCT1_RESEARCH_END_AVAILABLE)
+ if (researchItem.item == RCT1_RESEARCH_END_AVAILABLE)
{
researched = false;
continue;
}
// We don't import the random items yet.
- else if (researchItem->item == RCT1_RESEARCH_END_RESEARCHABLE || researchItem->item == RCT1_RESEARCH_END)
+ else if (researchItem.item == RCT1_RESEARCH_END_RESEARCHABLE || researchItem.item == RCT1_RESEARCH_END)
{
break;
}
}
- switch (researchItem->type)
+ switch (researchItem.type)
{
case RCT1_RESEARCH_TYPE_THEME:
{
- uint8_t rct1SceneryTheme = researchItem->item;
+ uint8_t rct1SceneryTheme = researchItem.item;
auto sceneryGroupEntryIndex = _sceneryThemeTypeToEntryMap[rct1SceneryTheme];
if (sceneryGroupEntryIndex != OBJECT_ENTRY_INDEX_IGNORE
&& sceneryGroupEntryIndex != OBJECT_ENTRY_INDEX_NULL)
@@ -1929,7 +1928,7 @@ namespace RCT1
}
case RCT1_RESEARCH_TYPE_RIDE:
{
- uint8_t rct1RideType = researchItem->item;
+ uint8_t rct1RideType = researchItem.item;
_researchRideTypeUsed[rct1RideType] = true;
auto ownRideEntryIndex = _rideTypeToRideEntryMap[rct1RideType];
@@ -1943,11 +1942,11 @@ namespace RCT1
// Add all vehicles for this ride type that are researched or before this research item
for (size_t j = 0; j < researchListCount; j++)
{
- const rct1_research_item* researchItem2 = &researchList[j];
- if (researchItem2->flags == RCT1_RESEARCH_FLAGS_SEPARATOR)
+ const auto& researchItem2 = researchList[j];
+ if (researchItem2.flags == RCT1_RESEARCH_FLAGS_SEPARATOR)
{
- if (researchItem2->item == RCT1_RESEARCH_END_RESEARCHABLE
- || researchItem2->item == RCT1_RESEARCH_END)
+ if (researchItem2.item == RCT1_RESEARCH_END_RESEARCHABLE
+ || researchItem2.item == RCT1_RESEARCH_END)
{
break;
}
@@ -1955,10 +1954,10 @@ namespace RCT1
continue;
}
- if (researchItem2->type == RCT1_RESEARCH_TYPE_VEHICLE
- && researchItem2->related_ride == rct1RideType)
+ if (researchItem2.type == RCT1_RESEARCH_TYPE_VEHICLE
+ && researchItem2.related_ride == rct1RideType)
{
- auto rideEntryIndex2 = _vehicleTypeToRideEntryMap[researchItem2->item];
+ auto rideEntryIndex2 = _vehicleTypeToRideEntryMap[researchItem2.item];
bool isOwnType = (ownRideEntryIndex == rideEntryIndex2);
if (isOwnType)
{
@@ -1991,13 +1990,13 @@ namespace RCT1
// Only add vehicle if the related ride has been seen, this to make sure that vehicles
// are researched only after the ride has been researched. Otherwise, remove them from the research
// list, so that they are automatically co-invented when their master ride is invented.
- if (_researchRideTypeUsed[researchItem->related_ride])
+ if (_researchRideTypeUsed[researchItem.related_ride])
{
InsertResearchVehicle(researchItem, researched);
}
- else if (!rideTypeInResearch[researchItem->related_ride] && _gameVersion == FILE_VERSION_RCT1_LL)
+ else if (!rideTypeInResearch[researchItem.related_ride] && _gameVersion == FILE_VERSION_RCT1_LL)
{
- vehiclesWithMissingRideTypes.push_back(*researchItem);
+ vehiclesWithMissingRideTypes.push_back(researchItem);
}
break;
@@ -2007,9 +2006,9 @@ namespace RCT1
break;
}
}
- for (const rct1_research_item& researchItem : vehiclesWithMissingRideTypes)
+ for (const auto& researchItem : vehiclesWithMissingRideTypes)
{
- InsertResearchVehicle(&researchItem, false);
+ InsertResearchVehicle(researchItem, false);
}
// Research funding / priority
@@ -2055,7 +2054,7 @@ namespace RCT1
}
else
{
- ResearchItem researchItem = {};
+ ::ResearchItem researchItem = {};
ConvertResearchEntry(&researchItem, _s4.last_research_item, _s4.last_research_type);
gResearchLastItem = researchItem;
}
@@ -2068,45 +2067,44 @@ namespace RCT1
}
else
{
- ResearchItem researchItem = {};
+ ::ResearchItem researchItem = {};
ConvertResearchEntry(&researchItem, _s4.next_research_item, _s4.next_research_type);
gResearchNextItem = researchItem;
}
}
static std::bitset GetRideTypesPresentInResearchList(
- const rct1_research_item* researchList, size_t researchListCount)
+ const RCT1::ResearchItem* researchList, size_t researchListCount)
{
std::bitset ret = {};
for (size_t i = 0; i < researchListCount; i++)
{
- const rct1_research_item* researchItem = &researchList[i];
- if (researchItem->flags == RCT1_RESEARCH_FLAGS_SEPARATOR)
+ const auto& researchItem = researchList[i];
+ if (researchItem.flags == RCT1_RESEARCH_FLAGS_SEPARATOR)
{
- if (researchItem->item == RCT1_RESEARCH_END_AVAILABLE
- || researchItem->item == RCT1_RESEARCH_END_RESEARCHABLE)
+ if (researchItem.item == RCT1_RESEARCH_END_AVAILABLE || researchItem.item == RCT1_RESEARCH_END_RESEARCHABLE)
{
continue;
}
- else if (researchItem->item == RCT1_RESEARCH_END)
+ else if (researchItem.item == RCT1_RESEARCH_END)
{
break;
}
}
- if (researchItem->type == RCT1_RESEARCH_TYPE_RIDE)
+ if (researchItem.type == RCT1_RESEARCH_TYPE_RIDE)
{
- ret[researchItem->item] = true;
+ ret[researchItem.item] = true;
}
}
return ret;
}
- void InsertResearchVehicle(const rct1_research_item* researchItem, bool researched)
+ void InsertResearchVehicle(const ResearchItem& researchItem, bool researched)
{
- uint8_t vehicle = researchItem->item;
+ uint8_t vehicle = researchItem.item;
auto rideEntryIndex = _vehicleTypeToRideEntryMap[vehicle];
if (!_researchRideEntryUsed[rideEntryIndex])
@@ -2184,7 +2182,7 @@ namespace RCT1
uint8_t researchItem = src->Assoc & 0x000000FF;
uint8_t researchType = (src->Assoc & 0x00FF0000) >> 16;
- ResearchItem tmpResearchItem = {};
+ ::ResearchItem tmpResearchItem = {};
ConvertResearchEntry(&tmpResearchItem, researchItem, researchType);
dst->Assoc = tmpResearchItem.rawValue;
}
@@ -2228,7 +2226,7 @@ namespace RCT1
gTotalRideValueForMoney = _s4.total_ride_value_for_money;
}
- void ConvertResearchEntry(ResearchItem* dst, uint8_t srcItem, uint8_t srcType)
+ void ConvertResearchEntry(::ResearchItem* dst, uint8_t srcItem, uint8_t srcType)
{
dst->SetNull();
if (srcType == RCT1_RESEARCH_TYPE_RIDE)
@@ -2463,7 +2461,7 @@ namespace RCT1
return nullptr;
}
- const rct1_research_item* GetResearchList(size_t* count)
+ const RCT1::ResearchItem* GetResearchList(size_t* count)
{
// Loopy Landscapes stores research items in a different place
if (_gameVersion == FILE_VERSION_RCT1_LL)
@@ -2626,7 +2624,7 @@ namespace RCT1
ObjectEntryIndex GetBuildTheBestRideId()
{
size_t researchListCount;
- const rct1_research_item* researchList = GetResearchList(&researchListCount);
+ const RCT1::ResearchItem* researchList = GetResearchList(&researchListCount);
for (size_t i = 0; i < researchListCount; i++)
{
if (researchList[i].flags == 0xFF)
@@ -2654,7 +2652,7 @@ namespace RCT1
output = EntityType::Vehicle;
break;
case RCT12SpriteIdentifier::Peep:
- if (RCT12PeepType(static_cast(&src)->type) == RCT12PeepType::Guest)
+ if (RCT12PeepType(static_cast(&src)->type) == RCT12PeepType::Guest)
{
output = EntityType::Guest;
}
@@ -2708,10 +2706,10 @@ namespace RCT1
return output;
}
- template<> void S4Importer::ImportEntity(const RCT12SpriteBase& srcBase)
+ template<> void S4Importer::ImportEntity<::Vehicle>(const RCT12SpriteBase& srcBase)
{
- auto* dst = CreateEntityAt(srcBase.sprite_index);
- auto* src = static_cast(&srcBase);
+ auto* dst = CreateEntityAt<::Vehicle>(srcBase.sprite_index);
+ auto* src = static_cast(&srcBase);
const auto* ride = get_ride(src->ride);
if (ride == nullptr)
return;
@@ -2722,7 +2720,7 @@ namespace RCT1
dst->ride_subtype = RCTEntryIndexToOpenRCT2EntryIndex(ride->subtype);
dst->vehicle_type = vehicleEntryIndex;
- dst->SubType = Vehicle::Type(src->type);
+ dst->SubType = ::Vehicle::Type(src->type);
dst->var_44 = src->var_44;
dst->remaining_distance = src->remaining_distance;
@@ -2759,7 +2757,6 @@ namespace RCT1
dst->var_C4 = src->var_C4;
dst->animation_frame = src->animation_frame;
dst->animationState = src->animationState;
- dst->var_CA = src->var_CA;
dst->var_CE = src->var_CE;
dst->var_D3 = src->var_D3;
dst->scream_sound_id = OpenRCT2::Audio::SoundId::Null;
@@ -2786,16 +2783,16 @@ namespace RCT1
}
}
- Vehicle::Status statusSrc = Vehicle::Status::MovingToEndOfStation;
- if (src->status <= static_cast(Vehicle::Status::StoppedByBlockBrakes))
+ ::Vehicle::Status statusSrc = ::Vehicle::Status::MovingToEndOfStation;
+ if (src->status <= static_cast(::Vehicle::Status::StoppedByBlockBrakes))
{
- statusSrc = static_cast(src->status);
+ statusSrc = static_cast<::Vehicle::Status>(src->status);
}
dst->status = statusSrc;
dst->TrackSubposition = VehicleTrackSubposition{ src->TrackSubposition };
dst->TrackLocation = { src->track_x, src->track_y, src->track_z };
dst->current_station = src->current_station;
- if (src->boat_location.isNull() || ride->mode != RideMode::BoatHire || statusSrc != Vehicle::Status::TravellingBoat)
+ if (src->boat_location.isNull() || ride->mode != RideMode::BoatHire || statusSrc != ::Vehicle::Status::TravellingBoat)
{
dst->BoatLocation.setNull();
dst->SetTrackDirection(src->GetTrackDirection());
@@ -2827,7 +2824,7 @@ namespace RCT1
template<> void S4Importer::ImportEntity(const RCT12SpriteBase& srcBase)
{
auto* dst = CreateEntityAt(srcBase.sprite_index);
- auto* src = static_cast(&srcBase);
+ auto* src = static_cast(&srcBase);
ImportPeep(dst, src);
dst->OutsideOfPark = static_cast(src->outside_of_park);
@@ -2886,14 +2883,10 @@ namespace RCT1
auto srcThought = &src->thoughts[i];
auto dstThought = &dst->Thoughts[i];
dstThought->type = static_cast(srcThought->type);
- if (srcThought->item == 255)
- {
- dstThought->argument = std::numeric_limits::max();
- }
+ if (srcThought->item == RCT12PeepThoughtItemNone)
+ dstThought->item = PeepThoughtItemNone;
else
- {
- dstThought->argument = srcThought->item;
- }
+ dstThought->item = srcThought->item;
dstThought->freshness = srcThought->freshness;
dstThought->fresh_timeout = srcThought->fresh_timeout;
}
@@ -2931,7 +2924,7 @@ namespace RCT1
template<> void S4Importer::ImportEntity(const RCT12SpriteBase& srcBase)
{
auto* dst = CreateEntityAt(srcBase.sprite_index);
- auto* src = static_cast(&srcBase);
+ auto* src = static_cast(&srcBase);
ImportPeep(dst, src);
dst->AssignedStaffType = StaffType(src->staff_type);
dst->MechanicTimeSinceCall = src->mechanic_time_since_call;
@@ -3050,7 +3043,7 @@ namespace RCT1
switch (GetEntityTypeFromRCT1Sprite(src))
{
case EntityType::Vehicle:
- ImportEntity(src);
+ ImportEntity<::Vehicle>(src);
break;
case EntityType::Guest:
ImportEntity(src);
diff --git a/src/openrct2/rct1/T4Importer.cpp b/src/openrct2/rct1/T4Importer.cpp
index f72884f59d..be246fd497 100644
--- a/src/openrct2/rct1/T4Importer.cpp
+++ b/src/openrct2/rct1/T4Importer.cpp
@@ -95,8 +95,8 @@ namespace RCT1
std::unique_ptr ImportAA()
{
std::unique_ptr td = std::make_unique();
- rct_track_td4_aa td4aa{};
- _stream.Read(&td4aa, sizeof(rct_track_td4_aa));
+ TD4AA td4aa{};
+ _stream.Read(&td4aa, sizeof(TD4AA));
for (int32_t i = 0; i < RCT12_NUM_COLOUR_SCHEMES; i++)
{
@@ -113,8 +113,8 @@ namespace RCT1
std::unique_ptr ImportTD4()
{
std::unique_ptr td = std::make_unique();
- rct_track_td4 td4{};
- _stream.Read(&td4, sizeof(rct_track_td4));
+ TD4 td4{};
+ _stream.Read(&td4, sizeof(TD4));
for (int32_t i = 0; i < NUM_COLOUR_SCHEMES; i++)
{
td->track_spine_colour[i] = RCT1::GetColour(td4.track_spine_colour_v0);
@@ -137,7 +137,7 @@ namespace RCT1
return ImportTD4Base(std::move(td), td4);
}
- std::unique_ptr ImportTD4Base(std::unique_ptr td, rct_track_td4& td4Base)
+ std::unique_ptr ImportTD4Base(std::unique_ptr td, TD4& td4Base)
{
td->type = RCT1::GetRideType(td4Base.type, td4Base.vehicle_type);
@@ -169,7 +169,7 @@ namespace RCT1
for (int32_t i = 0; i < RCT1_MAX_TRAINS_PER_RIDE; i++)
{
// RCT1 had no third colour
- RCT1::RCT1VehicleColourSchemeCopyDescriptor colourSchemeCopyDescriptor = RCT1::GetColourSchemeCopyDescriptor(
+ RCT1::VehicleColourSchemeCopyDescriptor colourSchemeCopyDescriptor = RCT1::GetColourSchemeCopyDescriptor(
td4Base.vehicle_type);
if (colourSchemeCopyDescriptor.colour1 == COPY_COLOUR_1)
{
diff --git a/src/openrct2/rct1/Tables.cpp b/src/openrct2/rct1/Tables.cpp
index 78c99645c2..5922210c9a 100644
--- a/src/openrct2/rct1/Tables.cpp
+++ b/src/openrct2/rct1/Tables.cpp
@@ -263,9 +263,9 @@ namespace RCT1
return map[rideType];
}
- RCT1VehicleColourSchemeCopyDescriptor GetColourSchemeCopyDescriptor(uint8_t vehicleType)
+ VehicleColourSchemeCopyDescriptor GetColourSchemeCopyDescriptor(uint8_t vehicleType)
{
- static RCT1VehicleColourSchemeCopyDescriptor map[89] =
+ static VehicleColourSchemeCopyDescriptor map[89] =
{
{ COPY_COLOUR_1, COPY_COLOUR_2, COLOUR_BLACK }, // RCT1_VEHICLE_TYPE_STEEL_ROLLER_COASTER_TRAIN = 0,
{ COPY_COLOUR_1, COPY_COLOUR_2, COLOUR_BLACK }, // RCT1_VEHICLE_TYPE_STEEL_ROLLER_COASTER_TRAIN_BACKWARDS,
diff --git a/src/openrct2/rct1/Tables.h b/src/openrct2/rct1/Tables.h
index e72bef6a67..005fb7d73b 100644
--- a/src/openrct2/rct1/Tables.h
+++ b/src/openrct2/rct1/Tables.h
@@ -16,7 +16,7 @@
namespace RCT1
{
- struct RCT1VehicleColourSchemeCopyDescriptor
+ struct VehicleColourSchemeCopyDescriptor
{
int8_t colour1, colour2, colour3;
};
@@ -25,7 +25,7 @@ namespace RCT1
PeepSpriteType GetPeepSpriteType(uint8_t rct1SpriteType);
uint8_t GetRideType(uint8_t rideType, uint8_t vehicleType);
- RCT1VehicleColourSchemeCopyDescriptor GetColourSchemeCopyDescriptor(uint8_t vehicleType);
+ VehicleColourSchemeCopyDescriptor GetColourSchemeCopyDescriptor(uint8_t vehicleType);
bool RideTypeUsesVehicles(uint8_t rideType);
bool PathIsQueue(uint8_t pathType);
uint8_t NormalisePathAddition(uint8_t pathAdditionType);
diff --git a/src/openrct2/rct12/RCT12.h b/src/openrct2/rct12/RCT12.h
index 2d604bed54..1a9d730b5d 100644
--- a/src/openrct2/rct12/RCT12.h
+++ b/src/openrct2/rct12/RCT12.h
@@ -90,6 +90,8 @@ constexpr const uint16_t RCT12_PEEP_SPAWN_UNDEFINED = 0xFFFF;
constexpr const uint16_t RCT12VehicleTrackDirectionMask = 0b0000000000000011;
constexpr const uint16_t RCT12VehicleTrackTypeMask = 0b1111111111111100;
+constexpr const uint8_t RCT12PeepThoughtItemNone = std::numeric_limits::max();
+
enum class RCT12TrackDesignVersion : uint8_t
{
TD4,
diff --git a/src/openrct2/rct2/RCT2.h b/src/openrct2/rct2/RCT2.h
index 9eed039d9b..24e1346ff0 100644
--- a/src/openrct2/rct2/RCT2.h
+++ b/src/openrct2/rct2/RCT2.h
@@ -15,6 +15,7 @@
#include "../rct12/RCT12.h"
#include "../ride/RideRatings.h"
#include "../ride/VehicleColour.h"
+#include "../world/EntityList.h"
#include
#include
@@ -38,6 +39,8 @@ constexpr const uint8_t RCT2_MAX_RESEARCHED_RIDE_ENTRY_QUADS = 8; // With 32 bit
constexpr const uint8_t RCT2_MAX_RESEARCHED_SCENERY_ITEM_QUADS = 56;
constexpr const uint16_t RCT2_MAX_RESEARCHED_SCENERY_ITEMS = (RCT2_MAX_RESEARCHED_SCENERY_ITEM_QUADS * 32); // There are 32 bits
// per quad.
+constexpr const uint16_t RCT2_MAX_RESEARCH_ITEMS = 500;
+
constexpr uint16_t TD6MaxTrackElements = 8192;
constexpr const uint8_t RCT2_MAX_SMALL_SCENERY_OBJECTS = 252;
@@ -538,8 +541,7 @@ struct RCT2SpriteVehicle : RCT12SpriteBase
};
uint8_t animation_frame; // 0xC5
uint8_t pad_C6[0x2];
- uint16_t animationState;
- uint16_t var_CA;
+ uint32_t animationState;
uint8_t scream_sound_id; // 0xCC
uint8_t TrackSubposition;
union
@@ -787,6 +789,263 @@ struct RCT2RideRatingCalculationData
};
assert_struct_size(RCT2RideRatingCalculationData, 76);
+/**
+ * SV6/SC6 header chunk
+ * size: 0x20
+ */
+struct rct_s6_header
+{
+ uint8_t type; // 0x00
+ uint8_t classic_flag; // 0x01
+ uint16_t num_packed_objects; // 0x02
+ uint32_t version; // 0x04
+ uint32_t magic_number; // 0x08
+ uint8_t pad_0C[0x14];
+};
+assert_struct_size(rct_s6_header, 0x20);
+
+enum class EditorStep : uint8_t;
+
+/**
+ * SC6 information chunk
+ * size: 0x198
+ */
+struct rct_s6_info
+{
+ EditorStep editor_step;
+ uint8_t category; // 0x01
+ uint8_t objective_type; // 0x02
+ uint8_t objective_arg_1; // 0x03
+ int32_t objective_arg_2; // 0x04
+ int16_t objective_arg_3; // 0x08
+ uint8_t pad_00A[0x3E];
+ char name[64]; // 0x48
+ char details[256]; // 0x88
+ rct_object_entry entry; // 0x188
+};
+assert_struct_size(rct_s6_info, 0x198);
+
+struct rct_s6_data
+{
+ // SC6[0]
+ rct_s6_header header;
+
+ // SC6[1]
+ rct_s6_info info;
+
+ // SC6[2]
+ // packed objects
+
+ // SC6[3]
+ rct_object_entry objects[RCT2_OBJECT_ENTRY_COUNT];
+
+ // SC6[4]
+ uint16_t elapsed_months;
+ uint16_t current_day;
+ uint32_t scenario_ticks;
+ uint32_t scenario_srand_0;
+ uint32_t scenario_srand_1;
+
+ // SC6[5]
+ RCT12TileElement tile_elements[RCT2_MAX_TILE_ELEMENTS];
+
+ // SC6[6]
+ uint32_t next_free_tile_element_pointer_index;
+ RCT2Sprite sprites[RCT2_MAX_SPRITES];
+ uint16_t sprite_lists_head[static_cast(EntityListId::Count)];
+ uint16_t sprite_lists_count[static_cast(EntityListId::Count)];
+ rct_string_id park_name;
+ uint8_t pad_013573D6[2];
+ uint32_t park_name_args;
+ money32 initial_cash;
+ money32 current_loan;
+ uint32_t park_flags;
+ money16 park_entrance_fee;
+ uint16_t rct1_park_entrance_x;
+ uint16_t rct1_park_entrance_y;
+ uint8_t pad_013573EE[2];
+ uint8_t rct1_park_entrance_z;
+ uint8_t pad_013573F1;
+ rct12_peep_spawn peep_spawns[RCT12_MAX_PEEP_SPAWNS];
+ uint8_t guest_count_change_modifier;
+ uint8_t current_research_level;
+ uint8_t pad_01357400[4];
+ uint32_t researched_ride_types[RCT2_MAX_RESEARCHED_RIDE_TYPE_QUADS];
+ uint32_t researched_ride_entries[RCT2_MAX_RESEARCHED_RIDE_ENTRY_QUADS];
+ uint32_t researched_track_types_a[128];
+ uint32_t researched_track_types_b[128];
+
+ // SC6[7]
+ uint16_t guests_in_park;
+ uint16_t guests_heading_for_park;
+
+ // Ignored in scenario
+ money32 expenditure_table[RCT12_EXPENDITURE_TABLE_MONTH_COUNT][RCT12_EXPENDITURE_TYPE_COUNT];
+
+ // SC6[8]
+ uint16_t last_guests_in_park;
+ uint8_t pad_01357BCA[3];
+ uint8_t handyman_colour;
+ uint8_t mechanic_colour;
+ uint8_t security_colour;
+
+ // Ignored in scenario
+ uint32_t researched_scenery_items[RCT2_MAX_RESEARCHED_SCENERY_ITEM_QUADS];
+
+ // SC6[9]
+ uint16_t park_rating;
+
+ // Ignored in scenario
+ uint8_t park_rating_history[32];
+ uint8_t guests_in_park_history[32];
+
+ // SC6[10]
+ uint8_t active_research_types;
+ uint8_t research_progress_stage;
+ uint32_t last_researched_item_subject;
+ uint8_t pad_01357CF8[1000];
+ uint32_t next_research_item;
+ uint16_t research_progress;
+ uint8_t next_research_category;
+ uint8_t next_research_expected_day;
+ uint8_t next_research_expected_month;
+ uint8_t guest_initial_happiness;
+ uint16_t park_size;
+ uint16_t guest_generation_probability;
+ uint16_t total_ride_value_for_money;
+ money32 maximum_loan;
+ money16 guest_initial_cash;
+ uint8_t guest_initial_hunger;
+ uint8_t guest_initial_thirst;
+ uint8_t objective_type;
+ uint8_t objective_year;
+ uint8_t pad_013580FA[2];
+ money32 objective_currency;
+ uint16_t objective_guests;
+ uint8_t campaign_weeks_left[20];
+ uint8_t campaign_ride_index[22];
+
+ // Ignored in scenario
+ money32 balance_history[RCT12_FINANCE_GRAPH_SIZE];
+
+ // SC6[11]
+ money32 current_expenditure;
+ money32 current_profit;
+ money32 weekly_profit_average_dividend;
+ uint16_t weekly_profit_average_divisor;
+ uint8_t pad_0135833A[2];
+
+ // Ignored in scenario
+ money32 weekly_profit_history[RCT12_FINANCE_GRAPH_SIZE];
+
+ // SC6[12]
+ money32 park_value;
+
+ // Ignored in scenario
+ money32 park_value_history[RCT12_FINANCE_GRAPH_SIZE];
+
+ // SC6[13]
+ money32 completed_company_value;
+ uint32_t total_admissions;
+ money32 income_from_admissions;
+ money32 company_value;
+ uint8_t peep_warning_throttle[16];
+ rct12_award awards[RCT12_MAX_AWARDS];
+ money16 land_price;
+ money16 construction_rights_price;
+ uint16_t word_01358774;
+ uint8_t pad_01358776[2];
+ uint32_t cd_key;
+ uint8_t pad_0135877C[64];
+ uint32_t game_version_number;
+ money32 completed_company_value_record;
+ uint32_t loan_hash;
+ uint16_t ride_count;
+ uint8_t pad_013587CA[6];
+ money32 historical_profit;
+ uint8_t pad_013587D4[4];
+ char scenario_completed_name[32];
+ money32 cash;
+ uint8_t pad_013587FC[50];
+ uint16_t park_rating_casualty_penalty;
+ uint16_t map_size_units;
+ uint16_t map_size_minus_2;
+ uint16_t map_size;
+ uint16_t map_max_xy;
+ uint32_t same_price_throughout;
+ uint16_t suggested_max_guests;
+ uint16_t park_rating_warning_days;
+ uint8_t last_entrance_style;
+ uint8_t rct1_water_colour;
+ uint8_t pad_01358842[2];
+ RCT12ResearchItem research_items[RCT2_MAX_RESEARCH_ITEMS];
+ uint16_t map_base_z;
+ char scenario_name[64];
+ char scenario_description[256];
+ uint8_t current_interest_rate;
+ uint8_t pad_0135934B;
+ uint32_t same_price_throughout_extended;
+ int16_t park_entrance_x[RCT12_MAX_PARK_ENTRANCES];
+ int16_t park_entrance_y[RCT12_MAX_PARK_ENTRANCES];
+ int16_t park_entrance_z[RCT12_MAX_PARK_ENTRANCES];
+ uint8_t park_entrance_direction[RCT12_MAX_PARK_ENTRANCES];
+ char scenario_filename[256];
+ uint8_t saved_expansion_pack_names[3256];
+ RCT12Banner banners[RCT2_MAX_BANNERS_IN_PARK];
+ char custom_strings[RCT12_MAX_USER_STRINGS][RCT12_USER_STRING_MAX_LENGTH];
+ uint32_t game_ticks_1;
+ rct2_ride rides[RCT12_MAX_RIDES_IN_PARK];
+ uint16_t saved_age;
+ int16_t saved_view_x;
+ int16_t saved_view_y;
+ uint8_t saved_view_zoom;
+ uint8_t saved_view_rotation;
+ RCT12MapAnimation map_animations[RCT2_MAX_ANIMATED_OBJECTS];
+ uint16_t num_map_animations;
+ uint8_t pad_0138B582[2];
+ RCT2RideRatingCalculationData ride_ratings_calc_data;
+ uint8_t pad_0138B5D0[60];
+ RCT12RideMeasurement ride_measurements[8];
+ uint32_t next_guest_index;
+ uint16_t grass_and_scenery_tilepos;
+ uint32_t patrol_areas[(RCT2_MAX_STAFF + RCT12_STAFF_TYPE_COUNT) * RCT12_PATROL_AREA_SIZE];
+ uint8_t staff_modes[RCT2_MAX_STAFF + RCT12_STAFF_TYPE_COUNT];
+ uint8_t pad_13CA73E;
+ uint8_t pad_13CA73F;
+ uint8_t byte_13CA740;
+ uint8_t pad_13CA741;
+ uint8_t byte_13CA742[4]; // unused
+ uint8_t climate;
+ uint8_t pad_013CA747;
+ uint16_t climate_update_timer;
+ uint8_t current_weather;
+ uint8_t next_weather;
+ uint8_t temperature;
+ uint8_t next_temperature;
+ uint8_t current_weather_effect;
+ uint8_t next_weather_effect;
+ uint8_t current_weather_gloom;
+ uint8_t next_weather_gloom;
+ uint8_t current_weather_level;
+ uint8_t next_weather_level;
+ rct12_news_item news_items[RCT12_MAX_NEWS_ITEMS];
+ char rct1_scenario_name[62]; // Unused in RCT2
+ uint16_t rct1_scenario_slot_index; // Unused in RCT2
+ uint32_t rct1_scenario_flags; // Unused in RCT2
+ uint16_t wide_path_tile_loop_x;
+ uint16_t wide_path_tile_loop_y;
+ uint8_t pad_13CE778[434];
+};
+assert_struct_size(rct_s6_data, 0x46b44a);
+
+struct rct_stex_entry
+{
+ rct_string_id scenario_name; // 0x00
+ rct_string_id park_name; // 0x02
+ rct_string_id details; // 0x04
+ uint8_t var_06;
+};
+assert_struct_size(rct_stex_entry, 7);
#pragma pack(pop)
std::vector DecryptSea(const fs::path& path);
diff --git a/src/openrct2/rct2/S6Importer.cpp b/src/openrct2/rct2/S6Importer.cpp
index 30a1fbcdef..9728faa3a3 100644
--- a/src/openrct2/rct2/S6Importer.cpp
+++ b/src/openrct2/rct2/S6Importer.cpp
@@ -1746,7 +1746,6 @@ template<> void S6Importer::ImportEntity(const RCT12SpriteBase& baseSrc
dst->dodgems_collision_direction = src->dodgems_collision_direction;
dst->animation_frame = src->animation_frame;
dst->animationState = src->animationState;
- dst->var_CA = src->var_CA;
dst->scream_sound_id = static_cast(src->scream_sound_id);
dst->TrackSubposition = VehicleTrackSubposition{ src->TrackSubposition };
dst->var_CE = src->var_CE;
@@ -1804,14 +1803,10 @@ template<> void S6Importer::ImportEntity(const RCT12SpriteBase& baseSrc)
auto srcThought = &src->thoughts[i];
auto dstThought = &dst->Thoughts[i];
dstThought->type = static_cast(srcThought->type);
- if (srcThought->item == 255)
- {
- dstThought->argument = std::numeric_limits::max();
- }
+ if (srcThought->item == RCT12PeepThoughtItemNone)
+ dstThought->item = PeepThoughtItemNone;
else
- {
- dstThought->argument = srcThought->item;
- }
+ dstThought->item = srcThought->item;
dstThought->freshness = srcThought->freshness;
dstThought->fresh_timeout = srcThought->fresh_timeout;
}
diff --git a/src/openrct2/ride/CableLift.cpp b/src/openrct2/ride/CableLift.cpp
index 3432ed6b92..92d9bc43a2 100644
--- a/src/openrct2/ride/CableLift.cpp
+++ b/src/openrct2/ride/CableLift.cpp
@@ -55,7 +55,6 @@ Vehicle* cable_lift_segment_create(
current->var_C4 = 0;
current->animation_frame = 0;
current->animationState = 0;
- current->var_CA = 0;
current->scream_sound_id = OpenRCT2::Audio::SoundId::Null;
current->Pitch = 0;
current->bank_rotation = 0;
diff --git a/src/openrct2/ride/Ride.cpp b/src/openrct2/ride/Ride.cpp
index 0ed3a05e20..508d2a739f 100644
--- a/src/openrct2/ride/Ride.cpp
+++ b/src/openrct2/ride/Ride.cpp
@@ -73,6 +73,7 @@
#include
using namespace OpenRCT2;
+using namespace OpenRCT2::TrackMetaData;
RideMode& operator++(RideMode& d, int)
{
@@ -409,10 +410,11 @@ bool ride_try_get_origin_element(const Ride* ride, CoordsXYE* output)
// Found a track piece for target ride
// Check if it's not the station or ??? (but allow end piece of station)
+ const auto& ted = GetTrackElementDescriptor(it.element->AsTrack()->GetTrackType());
bool specialTrackPiece
= (it.element->AsTrack()->GetTrackType() != TrackElemType::BeginStation
&& it.element->AsTrack()->GetTrackType() != TrackElemType::MiddleStation
- && (TrackSequenceProperties[it.element->AsTrack()->GetTrackType()][0] & TRACK_SEQUENCE_FLAG_ORIGIN));
+ && (ted.SequenceProperties[0] & TRACK_SEQUENCE_FLAG_ORIGIN));
// Set result tile to this track piece if first found track or a ???
if (resultTileElement == nullptr || specialTrackPiece)
@@ -478,11 +480,12 @@ bool track_block_get_next_from_zero(
if (tileElement->IsGhost() != isGhost)
continue;
- auto nextTrackBlock = TrackBlocks[trackElement->GetTrackType()];
+ const auto& ted = GetTrackElementDescriptor(trackElement->GetTrackType());
+ const auto* nextTrackBlock = ted.Block;
if (nextTrackBlock == nullptr)
continue;
- auto nextTrackCoordinate = TrackCoordinates[trackElement->GetTrackType()];
+ const auto& nextTrackCoordinate = ted.Coordinates;
uint8_t nextRotation = tileElement->GetDirectionWithOffset(nextTrackCoordinate.rotation_begin)
| (nextTrackCoordinate.rotation_begin & TRACK_BLOCK_2);
@@ -519,6 +522,7 @@ bool track_block_get_next(CoordsXYE* input, CoordsXYE* output, int32_t* z, int32
return false;
auto inputElement = input->element->AsTrack();
+ const auto& ted = GetTrackElementDescriptor(inputElement->GetTrackType());
if (inputElement == nullptr)
return false;
@@ -527,13 +531,13 @@ bool track_block_get_next(CoordsXYE* input, CoordsXYE* output, int32_t* z, int32
if (ride == nullptr)
return false;
- auto trackBlock = TrackBlocks[inputElement->GetTrackType()];
+ const auto* trackBlock = ted.Block;
if (trackBlock == nullptr)
return false;
trackBlock += inputElement->GetSequenceIndex();
- auto trackCoordinate = TrackCoordinates[inputElement->GetTrackType()];
+ const auto& trackCoordinate = ted.Coordinates;
int32_t x = input->x;
int32_t y = input->y;
@@ -595,11 +599,11 @@ bool track_block_get_previous_from_zero(
if (trackElement->GetRideIndex() != ride->id)
continue;
- auto nextTrackBlock = TrackBlocks[trackElement->GetTrackType()];
+ const auto* ted = &GetTrackElementDescriptor(trackElement->GetTrackType());
+ const auto* nextTrackBlock = ted->Block;
if (nextTrackBlock == nullptr)
continue;
-
- auto nextTrackCoordinate = TrackCoordinates[trackElement->GetTrackType()];
+ const auto& nextTrackCoordinate = ted->Coordinates;
nextTrackBlock += trackElement->GetSequenceIndex();
if ((nextTrackBlock + 1)->index != 255)
@@ -631,7 +635,8 @@ bool track_block_get_previous_from_zero(
outTrackBeginEnd->begin_z = tileElement->GetBaseZ();
- auto nextTrackBlock2 = TrackBlocks[trackElement->GetTrackType()];
+ ted = &GetTrackElementDescriptor(trackElement->GetTrackType());
+ const auto* nextTrackBlock2 = ted->Block;
if (nextTrackBlock2 == nullptr)
continue;
@@ -663,6 +668,7 @@ bool track_block_get_previous(const CoordsXYE& trackPos, track_begin_end* outTra
return false;
auto trackElement = trackPos.element->AsTrack();
+ const auto& ted = GetTrackElementDescriptor(trackElement->GetTrackType());
if (trackElement == nullptr)
return false;
@@ -671,13 +677,13 @@ bool track_block_get_previous(const CoordsXYE& trackPos, track_begin_end* outTra
if (ride == nullptr)
return false;
- auto trackBlock = TrackBlocks[trackElement->GetTrackType()];
+ const auto* trackBlock = ted.Block;
if (trackBlock == nullptr)
return false;
trackBlock += trackElement->GetSequenceIndex();
- auto trackCoordinate = TrackCoordinates[trackElement->GetTrackType()];
+ auto trackCoordinate = ted.Coordinates;
int32_t z = trackElement->GetBaseZ();
@@ -2228,7 +2234,8 @@ static void ride_shop_connected(Ride* ride)
return;
}
- uint8_t entrance_directions = TrackSequenceProperties[track_type][0] & 0xF;
+ const auto& ted = GetTrackElementDescriptor(track_type);
+ uint8_t entrance_directions = ted.SequenceProperties[0] & 0xF;
uint8_t tile_direction = trackElement->GetDirection();
entrance_directions = rol4(entrance_directions, tile_direction);
@@ -2663,7 +2670,8 @@ static bool ride_check_track_contains_inversions(CoordsXYE* input, CoordsXYE* ou
while (track_circuit_iterator_next(&it))
{
auto trackType = it.current.element->AsTrack()->GetTrackType();
- if (TrackFlags[trackType] & TRACK_ELEM_FLAG_INVERSION_TO_NORMAL)
+ const auto& ted = GetTrackElementDescriptor(trackType);
+ if (ted.Flags & TRACK_ELEM_FLAG_INVERSION_TO_NORMAL)
{
*output = it.current;
return true;
@@ -2721,7 +2729,8 @@ static bool ride_check_track_contains_banked(CoordsXYE* input, CoordsXYE* output
while (track_circuit_iterator_next(&it))
{
auto trackType = output->element->AsTrack()->GetTrackType();
- if (TrackFlags[trackType] & TRACK_ELEM_FLAG_BANKED)
+ const auto& ted = GetTrackElementDescriptor(trackType);
+ if (ted.Flags & TRACK_ELEM_FLAG_BANKED)
{
*output = it.current;
return true;
@@ -2770,7 +2779,8 @@ static int32_t ride_check_station_length(CoordsXYE* input, CoordsXYE* output)
do
{
- if (TrackSequenceProperties[output->element->AsTrack()->GetTrackType()][0] & TRACK_SEQUENCE_FLAG_ORIGIN)
+ const auto& ted = GetTrackElementDescriptor(output->element->AsTrack()->GetTrackType());
+ if (ted.SequenceProperties[0] & TRACK_SEQUENCE_FLAG_ORIGIN)
{
num_station_elements++;
last_good_station = *output;
@@ -2817,7 +2827,8 @@ static bool ride_check_start_and_end_is_station(CoordsXYE* input)
// Check back of the track
track_get_back(input, &trackBack);
auto trackType = trackBack.element->AsTrack()->GetTrackType();
- if (!(TrackSequenceProperties[trackType][0] & TRACK_SEQUENCE_FLAG_ORIGIN))
+ const auto* ted = &GetTrackElementDescriptor(trackType);
+ if (!(ted->SequenceProperties[0] & TRACK_SEQUENCE_FLAG_ORIGIN))
{
return false;
}
@@ -2826,7 +2837,8 @@ static bool ride_check_start_and_end_is_station(CoordsXYE* input)
// Check front of the track
track_get_front(input, &trackFront);
trackType = trackFront.element->AsTrack()->GetTrackType();
- if (!(TrackSequenceProperties[trackType][0] & TRACK_SEQUENCE_FLAG_ORIGIN))
+ ted = &GetTrackElementDescriptor(trackType);
+ if (!(ted->SequenceProperties[0] & TRACK_SEQUENCE_FLAG_ORIGIN))
{
return false;
}
@@ -2862,7 +2874,8 @@ static void ride_set_boat_hire_return_point(Ride* ride, CoordsXYE* startElement)
};
trackType = returnPos.element->AsTrack()->GetTrackType();
- int32_t elementReturnDirection = TrackCoordinates[trackType].rotation_begin;
+ const auto& ted = GetTrackElementDescriptor(trackType);
+ int32_t elementReturnDirection = ted.Coordinates.rotation_begin;
ride->boat_hire_return_direction = returnPos.element->GetDirectionWithOffset(elementReturnDirection);
ride->boat_hire_return_position = TileCoordsXY{ returnPos };
}
@@ -3536,7 +3549,8 @@ static bool ride_initialise_cable_lift_track(Ride* ride, bool isApplying)
if (tileElement->GetBaseZ() != location.z)
continue;
- if (!(TrackSequenceProperties[tileElement->AsTrack()->GetTrackType()][0] & TRACK_SEQUENCE_FLAG_ORIGIN))
+ const auto& ted = GetTrackElementDescriptor(tileElement->AsTrack()->GetTrackType());
+ if (!(ted.SequenceProperties[0] & TRACK_SEQUENCE_FLAG_ORIGIN))
{
continue;
}
@@ -3768,8 +3782,8 @@ TrackElement* Ride::GetOriginElement(StationIndex stationIndex) const
continue;
auto* trackElement = tileElement->AsTrack();
-
- if (!(TrackSequenceProperties[trackElement->GetTrackType()][0] & TRACK_SEQUENCE_FLAG_ORIGIN))
+ const auto& ted = GetTrackElementDescriptor(trackElement->GetTrackType());
+ if (!(ted.SequenceProperties[0] & TRACK_SEQUENCE_FLAG_ORIGIN))
continue;
if (trackElement->GetRideIndex() == id)
@@ -4875,7 +4889,8 @@ static int32_t ride_get_track_length(Ride* ride)
continue;
trackType = tileElement->AsTrack()->GetTrackType();
- if (!(TrackSequenceProperties[trackType][0] & TRACK_SEQUENCE_FLAG_ORIGIN))
+ const auto& ted = GetTrackElementDescriptor(trackType);
+ if (!(ted.SequenceProperties[0] & TRACK_SEQUENCE_FLAG_ORIGIN))
continue;
if (tileElement->GetBaseZ() != trackStart.z)
@@ -4906,7 +4921,8 @@ static int32_t ride_get_track_length(Ride* ride)
while (track_circuit_iterator_next(&it))
{
trackType = it.current.element->AsTrack()->GetTrackType();
- result += TrackPieceLengths[trackType];
+ const auto& ted = GetTrackElementDescriptor(trackType);
+ result += ted.PieceLength;
moveSlowIt = !moveSlowIt;
if (moveSlowIt)
diff --git a/src/openrct2/ride/RideConstruction.cpp b/src/openrct2/ride/RideConstruction.cpp
index 8abc33ef60..de5f99dfd3 100644
--- a/src/openrct2/ride/RideConstruction.cpp
+++ b/src/openrct2/ride/RideConstruction.cpp
@@ -43,6 +43,7 @@
#include "TrainManager.h"
#include "Vehicle.h"
+using namespace OpenRCT2::TrackMetaData;
bool gGotoStartPlacementMode = false;
money16 gTotalRideValueForMoney;
@@ -87,6 +88,7 @@ RideConstructionState gRideEntranceExitPlacePreviousRideConstructionState;
Direction gRideEntranceExitPlaceDirection;
using namespace OpenRCT2;
+using namespace OpenRCT2::TrackMetaData;
static int32_t ride_check_if_construction_allowed(Ride* ride)
{
@@ -392,7 +394,8 @@ std::optional sub_6C683D(
}
// Possibly z should be & 0xF8
- auto trackBlock = TrackBlocks[type];
+ const auto& ted = GetTrackElementDescriptor(type);
+ const auto* trackBlock = ted.Block;
if (trackBlock == nullptr)
return std::nullopt;
@@ -626,6 +629,8 @@ void ride_construction_set_default_next_piece()
CoordsXYE xyElement;
TileElement* tileElement;
_currentTrackPrice = MONEY32_UNDEFINED;
+
+ const TrackElementDescriptor* ted;
switch (_rideConstructionState)
{
case RideConstructionState::Front:
@@ -654,7 +659,8 @@ void ride_construction_set_default_next_piece()
}
}
- curve = gTrackCurveChain[trackType].next;
+ ted = &GetTrackElementDescriptor(trackType);
+ curve = ted->CurveChain.next;
bank = TrackDefinitions[trackType].bank_end;
slope = TrackDefinitions[trackType].vangle_end;
@@ -699,7 +705,8 @@ void ride_construction_set_default_next_piece()
}
}
- curve = gTrackCurveChain[trackType].previous;
+ ted = &GetTrackElementDescriptor(trackType);
+ curve = ted->CurveChain.previous;
bank = TrackDefinitions[trackType].bank_start;
slope = TrackDefinitions[trackType].vangle_start;
@@ -1247,7 +1254,8 @@ CoordsXYZD ride_get_entrance_or_exit_position_from_screen_position(const ScreenC
{
if (info.Element->AsTrack()->GetRideIndex() == gRideEntranceExitPlaceRideIndex)
{
- if (TrackSequenceProperties[info.Element->AsTrack()->GetTrackType()][0] & TRACK_SEQUENCE_FLAG_ORIGIN)
+ const auto& ted = GetTrackElementDescriptor(info.Element->AsTrack()->GetTrackType());
+ if (ted.SequenceProperties[0] & TRACK_SEQUENCE_FLAG_ORIGIN)
{
if (info.Element->AsTrack()->GetTrackType() == TrackElemType::Maze)
{
@@ -1337,9 +1345,8 @@ CoordsXYZD ride_get_entrance_or_exit_position_from_screen_position(const ScreenC
int32_t eax = (entranceExitCoords.direction + 2 - tileElement->GetDirection())
& TILE_ELEMENT_DIRECTION_MASK;
- if (TrackSequenceProperties[tileElement->AsTrack()->GetTrackType()]
- [tileElement->AsTrack()->GetSequenceIndex()]
- & (1 << eax))
+ const auto& ted = GetTrackElementDescriptor(tileElement->AsTrack()->GetTrackType());
+ if (ted.SequenceProperties[tileElement->AsTrack()->GetSequenceIndex()] & (1 << eax))
{
entranceExitCoords.direction = direction_reverse(entranceExitCoords.direction);
gRideEntranceExitPlaceDirection = entranceExitCoords.direction;
@@ -1432,6 +1439,7 @@ CoordsXYZD ride_get_entrance_or_exit_position_from_screen_position(const ScreenC
*/
void sub_6CB945(Ride* ride)
{
+ const TrackElementDescriptor* ted;
if (ride->type != RIDE_TYPE_MAZE)
{
for (StationIndex stationId = 0; stationId < MAX_STATIONS; ++stationId)
@@ -1444,7 +1452,6 @@ void sub_6CB945(Ride* ride)
bool specialTrack = false;
TileElement* tileElement = nullptr;
-
while (true)
{
if (direction != INVALID_DIRECTION)
@@ -1467,7 +1474,9 @@ void sub_6CB945(Ride* ride)
continue;
if (tileElement->AsTrack()->GetSequenceIndex() != 0)
continue;
- if (!(TrackSequenceProperties[tileElement->AsTrack()->GetTrackType()][0] & TRACK_SEQUENCE_FLAG_ORIGIN))
+
+ ted = &GetTrackElementDescriptor(tileElement->AsTrack()->GetTrackType());
+ if (!(ted->SequenceProperties[0] & TRACK_SEQUENCE_FLAG_ORIGIN))
continue;
trackFound = true;
@@ -1494,7 +1503,8 @@ void sub_6CB945(Ride* ride)
continue;
}
- const rct_preview_track* trackBlock = TrackBlocks[tileElement->AsTrack()->GetTrackType()];
+ ted = &GetTrackElementDescriptor(tileElement->AsTrack()->GetTrackType());
+ const rct_preview_track* trackBlock = ted->Block;
while ((++trackBlock)->index != 0xFF)
{
CoordsXYZ blockLocation = location + CoordsXYZ{ CoordsXY{ trackBlock->x, trackBlock->y }.Rotate(direction), 0 };
@@ -1509,7 +1519,9 @@ void sub_6CB945(Ride* ride)
continue;
if (tileElement->GetType() != TILE_ELEMENT_TYPE_TRACK)
continue;
- if (!(TrackSequenceProperties[tileElement->AsTrack()->GetTrackType()][0] & TRACK_SEQUENCE_FLAG_ORIGIN))
+
+ ted = &GetTrackElementDescriptor(tileElement->AsTrack()->GetTrackType());
+ if (!(ted->SequenceProperties[0] & TRACK_SEQUENCE_FLAG_ORIGIN))
continue;
trackFound = true;
@@ -1604,7 +1616,8 @@ void sub_6CB945(Ride* ride)
Direction direction = (tileElement->GetDirection() - direction_reverse(trackElement->GetDirection())) & 3;
- if (!(TrackSequenceProperties[trackType][trackSequence] & (1 << direction)))
+ ted = &GetTrackElementDescriptor(trackType);
+ if (!(ted->SequenceProperties[trackSequence] & (1 << direction)))
{
continue;
}
diff --git a/src/openrct2/ride/TrackData.cpp b/src/openrct2/ride/TrackData.cpp
index 57e88855ca..f30a130642 100644
--- a/src/openrct2/ride/TrackData.cpp
+++ b/src/openrct2/ride/TrackData.cpp
@@ -12,10 +12,11 @@
#include "Track.h"
#include "TrackPaint.h"
+#include
#include
// clang-format off
-const rct_track_coordinates TrackCoordinates[TrackElemType::Count] = {
+static constexpr rct_track_coordinates TrackCoordinates[TrackElemType::Count] = {
{ 0, 0, 0, 0, 0, 0 }, // ELEM_FLAT
{ 0, 0, 0, 0, 0, 0 }, // ELEM_END_STATION
{ 0, 0, 0, 0, 0, 0 }, // ELEM_BEGIN_STATION
@@ -286,7 +287,7 @@ const rct_track_coordinates TrackCoordinates[TrackElemType::Count] = {
};
/** rct2: 0x0099BA64 */
-const uint8_t TrackSequenceProperties[][MaxSequencesPerPiece] = {
+static constexpr uint8_t TrackSequenceProperties[][MaxSequencesPerPiece] = {
{ 0 },
/* TrackElemType::EndStation */ { TRACK_SEQUENCE_FLAG_DIRECTION_1 | TRACK_SEQUENCE_FLAG_DIRECTION_3 | TRACK_SEQUENCE_FLAG_ORIGIN | TRACK_SEQUENCE_FLAG_DISALLOW_DOORS, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
/* TrackElemType::BeginStation */ { TRACK_SEQUENCE_FLAG_DIRECTION_1 | TRACK_SEQUENCE_FLAG_DIRECTION_3 | TRACK_SEQUENCE_FLAG_ORIGIN | TRACK_SEQUENCE_FLAG_DISALLOW_DOORS, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
@@ -558,7 +559,7 @@ const uint8_t TrackSequenceProperties[][MaxSequencesPerPiece] = {
#define TRACK_BLOCK_END { 255, 255, 255, 255, 255, {255, 255}, 255 }
-static constexpr const rct_preview_track TrackBlocks000[] = {
+static constexpr rct_preview_track TrackBlocks000[] = {
{ 0, 0, 0, 0, 0, { 0b1111, 0 }, 0 },
TRACK_BLOCK_END
};
@@ -2544,7 +2545,7 @@ static constexpr const rct_preview_track TrackBlocksFlatTrack3x3[] = {
};
// rct2: 0x00994638
-const rct_preview_track *TrackBlocks[TrackElemType::Count] = {
+static constexpr std::array TrackBlocks = {
TrackBlocks000,
TrackBlocks001,
TrackBlocks002,
@@ -2815,7 +2816,7 @@ const rct_preview_track *TrackBlocks[TrackElemType::Count] = {
TrackBlocksFlatTrack3x3,
};
-const uint8_t TrackPieceLengths[TrackElemType::Count] = {
+static constexpr uint8_t TrackPieceLengths[TrackElemType::Count] = {
32, // TrackElemType::Flat
32, // TrackElemType::EndStation
32, // TrackElemType::BeginStation
@@ -3086,7 +3087,7 @@ const uint8_t TrackPieceLengths[TrackElemType::Count] = {
};
// rct2: 0x00998C95
-const track_curve_chain gTrackCurveChain[TrackElemType::Count] = {
+static constexpr track_curve_chain gTrackCurveChain[TrackElemType::Count] = {
{ TRACK_CURVE_NONE, TRACK_CURVE_NONE },
{ RideConstructionSpecialPieceSelected | TrackElemType::EndStation, RideConstructionSpecialPieceSelected | TrackElemType::EndStation },
{ RideConstructionSpecialPieceSelected | TrackElemType::EndStation, RideConstructionSpecialPieceSelected | TrackElemType::EndStation },
@@ -3502,7 +3503,7 @@ const track_descriptor gTrackDescriptors[142] = {
};
/** rct2: 0x00993D1C */
-const track_type_t AlternativeTrackTypes[TrackElemType::Count] = {
+static constexpr track_type_t AlternativeTrackTypes[TrackElemType::Count] = {
TrackElemType::FlatCovered, // TrackElemType::Flat
TrackElemType::None,
TrackElemType::None,
@@ -3773,7 +3774,7 @@ const track_type_t AlternativeTrackTypes[TrackElemType::Count] = {
};
/** rct2: 0x0099DA34 */
-const money32 TrackPricing[TrackElemType::Count] = {
+static constexpr money32 TrackPricing[TrackElemType::Count] = {
65536, // TrackElemType::Flat
98304, // TrackElemType::EndStation
98304, // TrackElemType::BeginStation
@@ -4044,7 +4045,7 @@ const money32 TrackPricing[TrackElemType::Count] = {
};
/** rct2: 0x0099EA1C */
-const track_type_t TrackElementMirrorMap[TrackElemType::Count] = {
+static constexpr track_type_t TrackElementMirrorMap[TrackElemType::Count] = {
TrackElemType::Flat,
TrackElemType::EndStation,
TrackElemType::BeginStation,
@@ -4315,7 +4316,7 @@ const track_type_t TrackElementMirrorMap[TrackElemType::Count] = {
};
/** rct2: 0x00999694 */
-const uint32_t TrackHeightMarkerPositions[TrackElemType::Count] = {
+static constexpr uint32_t TrackHeightMarkerPositions[TrackElemType::Count] = {
(1 << 0), // TrackElemType::Flat
(1 << 0), // TrackElemType::EndStation
(1 << 0), // TrackElemType::BeginStation
@@ -4586,7 +4587,7 @@ const uint32_t TrackHeightMarkerPositions[TrackElemType::Count] = {
};
/** rct2: 0x00999A94 */
-const uint8_t TrackSequenceElementAllowedWallEdges[TrackElemType::Count][MaxSequencesPerPiece] = {
+static constexpr uint8_t TrackSequenceElementAllowedWallEdges[TrackElemType::Count][MaxSequencesPerPiece] = {
{ 0b1010, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // TrackElemType::Flat
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // TrackElemType::EndStation
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // TrackElemType::BeginStation
@@ -4857,7 +4858,7 @@ const uint8_t TrackSequenceElementAllowedWallEdges[TrackElemType::Count][MaxSequ
};
/** rct2: 0x0099423C */
-const uint16_t TrackFlags[TrackElemType::Count] = {
+static constexpr uint16_t TrackFlags[TrackElemType::Count] = {
/* TrackElemType::Flat */ TRACK_ELEM_FLAG_ALLOW_LIFT_HILL,
/* TrackElemType::EndStation */ 0,
/* TrackElemType::BeginStation */ 0,
@@ -5127,3 +5128,41 @@ const uint16_t TrackFlags[TrackElemType::Count] = {
/* TrackElemType::FlatTrack3x3 */ 0,
};
// clang-format on
+
+namespace OpenRCT2
+{
+ namespace TrackMetaData
+ {
+ static std::vector _trackElementDescriptors;
+ void Init()
+ {
+ _trackElementDescriptors.clear();
+ _trackElementDescriptors.reserve(TrackElemType::Count);
+
+ TrackElementDescriptor desc;
+ for (int i = 0; i < TrackElemType::Count; i++)
+ {
+ desc.AlternativeType = AlternativeTrackTypes[i];
+ desc.Block = const_cast(TrackBlocks[i]);
+ desc.Coordinates = TrackCoordinates[i];
+ desc.CurveChain = gTrackCurveChain[i];
+ desc.Flags = TrackFlags[i];
+ desc.HeightMarkerPositions = TrackHeightMarkerPositions[i];
+ desc.MirrorElement = TrackElementMirrorMap[i];
+ desc.PieceLength = TrackPieceLengths[i];
+ desc.Price = TrackPricing[i];
+
+ for (uint8_t j = 0; j < MaxSequencesPerPiece; j++)
+ {
+ desc.SequenceElementAllowedWallEdges[j] = TrackSequenceElementAllowedWallEdges[i][j];
+ desc.SequenceProperties[j] = TrackSequenceProperties[i][j];
+ }
+ _trackElementDescriptors.push_back(desc);
+ }
+ }
+ const TrackElementDescriptor& GetTrackElementDescriptor(const uint32_t type)
+ {
+ return _trackElementDescriptors[type];
+ }
+ } // namespace TrackMetaData
+} // namespace OpenRCT2
diff --git a/src/openrct2/ride/TrackData.h b/src/openrct2/ride/TrackData.h
index ba1dee8ee6..4cd3705355 100644
--- a/src/openrct2/ride/TrackData.h
+++ b/src/openrct2/ride/TrackData.h
@@ -16,13 +16,6 @@
constexpr const uint8_t MaxSequencesPerPiece = 16;
// 0x009968BB, 0x009968BC, 0x009968BD, 0x009968BF, 0x009968C1, 0x009968C3
-extern const rct_track_coordinates TrackCoordinates[TrackElemType::Count];
-
-extern const uint8_t TrackSequenceProperties[TrackElemType::Count][MaxSequencesPerPiece];
-
-extern const rct_preview_track* TrackBlocks[TrackElemType::Count];
-
-extern const uint8_t TrackPieceLengths[TrackElemType::Count];
struct track_curve_chain
{
@@ -30,8 +23,6 @@ struct track_curve_chain
int32_t previous;
};
-extern const track_curve_chain gTrackCurveChain[TrackElemType::Count];
-
struct track_descriptor
{
bool starts_diagonal;
@@ -45,10 +36,6 @@ struct track_descriptor
extern const track_descriptor gTrackDescriptors[142];
-extern const track_type_t AlternativeTrackTypes[TrackElemType::Count];
-
-extern const money32 TrackPricing[TrackElemType::Count];
-
struct dodgems_track_size
{
uint8_t left;
@@ -67,10 +54,29 @@ constexpr const dodgems_track_size DodgemsTrackSize(track_type_t type)
return { 4, 4, 59, 123 };
return { 0, 0, 0, 0 };
}
-extern const track_type_t TrackElementMirrorMap[TrackElemType::Count];
-extern const uint32_t TrackHeightMarkerPositions[TrackElemType::Count];
+struct TrackElementDescriptor
+{
+ rct_track_coordinates Coordinates;
-extern const uint8_t TrackSequenceElementAllowedWallEdges[TrackElemType::Count][16];
+ rct_preview_track* Block;
+ uint8_t PieceLength;
+ track_curve_chain CurveChain;
+ track_type_t AlternativeType;
+ money32 Price;
+ track_type_t MirrorElement;
+ uint32_t HeightMarkerPositions;
+ uint16_t Flags;
-extern const uint16_t TrackFlags[TrackElemType::Count];
+ std::array SequenceElementAllowedWallEdges;
+ std::array SequenceProperties;
+};
+
+namespace OpenRCT2
+{
+ namespace TrackMetaData
+ {
+ void Init();
+ const TrackElementDescriptor& GetTrackElementDescriptor(const uint32_t type);
+ } // namespace TrackMetaData
+} // namespace OpenRCT2
diff --git a/src/openrct2/ride/TrackDesign.cpp b/src/openrct2/ride/TrackDesign.cpp
index 4dfb151dc0..48ac02c8db 100644
--- a/src/openrct2/ride/TrackDesign.cpp
+++ b/src/openrct2/ride/TrackDesign.cpp
@@ -66,6 +66,7 @@
using namespace OpenRCT2;
using namespace OpenRCT2::Drawing;
+using namespace OpenRCT2::TrackMetaData;
bool gTrackDesignSceneryToggle;
static CoordsXYZ _trackPreviewMin;
@@ -190,8 +191,9 @@ rct_string_id TrackDesign::CreateTrackDesignTrack(const Ride& ride)
trackElement.y = newCoords->y;
z = newCoords->z;
- const rct_track_coordinates* trackCoordinates = &TrackCoordinates[trackElement.element->AsTrack()->GetTrackType()];
- auto trackBlock = TrackBlocks[trackType];
+ const auto& ted = GetTrackElementDescriptor(trackElement.element->AsTrack()->GetTrackType());
+ const rct_track_coordinates* trackCoordinates = &ted.Coordinates;
+ const auto* trackBlock = ted.Block;
// Used in the following loop to know when we have
// completed all of the elements and are back at the
// start.
@@ -875,7 +877,8 @@ static void track_design_mirror_ride(TrackDesign* td6)
{
for (auto& track : td6->track_elements)
{
- track.type = TrackElementMirrorMap[track.type];
+ const auto& ted = GetTrackElementDescriptor(track.type);
+ track.type = ted.MirrorElement;
}
for (auto& entrance : td6->entrance_elements)
@@ -1583,13 +1586,14 @@ static std::optional track_design_place_ride(TrackDesign* td6, const Co
for (const auto& track : td6->track_elements)
{
auto trackType = track.type;
+ const auto& ted = GetTrackElementDescriptor(trackType);
track_design_update_max_min_coordinates(newCoords);
switch (_trackDesignPlaceOperation)
{
case PTD_OPERATION_DRAW_OUTLINES:
- for (const rct_preview_track* trackBlock = TrackBlocks[trackType]; trackBlock->index != 0xFF; trackBlock++)
+ for (const rct_preview_track* trackBlock = ted.Block; trackBlock->index != 0xFF; trackBlock++)
{
auto tile = CoordsXY{ newCoords } + CoordsXY{ trackBlock->x, trackBlock->y }.Rotate(rotation);
track_design_update_max_min_coordinates({ tile, newCoords.z });
@@ -1598,8 +1602,8 @@ static std::optional track_design_place_ride(TrackDesign* td6, const Co
break;
case PTD_OPERATION_REMOVE_GHOST:
{
- const rct_track_coordinates* trackCoordinates = &TrackCoordinates[trackType];
- const rct_preview_track* trackBlock = TrackBlocks[trackType];
+ const rct_track_coordinates* trackCoordinates = &ted.Coordinates;
+ const rct_preview_track* trackBlock = ted.Block;
int32_t tempZ = newCoords.z - trackCoordinates->z_begin + trackBlock->z;
auto trackRemoveAction = TrackRemoveAction(
trackType, 0, { newCoords, tempZ, static_cast(rotation & 3) });
@@ -1613,7 +1617,7 @@ static std::optional track_design_place_ride(TrackDesign* td6, const Co
case PTD_OPERATION_PLACE_GHOST:
case PTD_OPERATION_PLACE_TRACK_PREVIEW:
{
- const rct_track_coordinates* trackCoordinates = &TrackCoordinates[trackType];
+ const rct_track_coordinates* trackCoordinates = &ted.Coordinates;
// di
int16_t tempZ = newCoords.z - trackCoordinates->z_begin;
@@ -1670,8 +1674,8 @@ static std::optional track_design_place_ride(TrackDesign* td6, const Co
}
case PTD_OPERATION_GET_PLACE_Z:
{
- int32_t tempZ = newCoords.z - TrackCoordinates[trackType].z_begin;
- for (const rct_preview_track* trackBlock = TrackBlocks[trackType]; trackBlock->index != 0xFF; trackBlock++)
+ int32_t tempZ = newCoords.z - ted.Coordinates.z_begin;
+ for (const rct_preview_track* trackBlock = ted.Block; trackBlock->index != 0xFF; trackBlock++)
{
auto tile = CoordsXY{ newCoords } + CoordsXY{ trackBlock->x, trackBlock->y }.Rotate(rotation);
if (!map_is_location_valid(tile))
@@ -1710,13 +1714,13 @@ static std::optional track_design_place_ride(TrackDesign* td6, const Co
}
}
- const rct_track_coordinates* track_coordinates = &TrackCoordinates[trackType];
+ const rct_track_coordinates& track_coordinates = ted.Coordinates;
auto offsetAndRotatedTrack = CoordsXY{ newCoords }
- + CoordsXY{ track_coordinates->x, track_coordinates->y }.Rotate(rotation);
+ + CoordsXY{ track_coordinates.x, track_coordinates.y }.Rotate(rotation);
- newCoords = { offsetAndRotatedTrack, newCoords.z - track_coordinates->z_begin + track_coordinates->z_end };
- rotation = (rotation + track_coordinates->rotation_end - track_coordinates->rotation_begin) & 3;
- if (track_coordinates->rotation_end & (1 << 2))
+ newCoords = { offsetAndRotatedTrack, newCoords.z - track_coordinates.z_begin + track_coordinates.z_end };
+ rotation = (rotation + track_coordinates.rotation_end - track_coordinates.rotation_begin) & 3;
+ if (track_coordinates.rotation_end & (1 << 2))
{
rotation |= (1 << 2);
}
diff --git a/src/openrct2/ride/TrackPaint.cpp b/src/openrct2/ride/TrackPaint.cpp
index b3e25f1e7e..d197375027 100644
--- a/src/openrct2/ride/TrackPaint.cpp
+++ b/src/openrct2/ride/TrackPaint.cpp
@@ -28,6 +28,8 @@
#include "TrackData.h"
#include "TrackDesign.h"
+using namespace OpenRCT2::TrackMetaData;
+
// clang-format off
/* rct2: 0x007667AC */
static constexpr TileCoordsXY EntranceOffsetEdgeNE[] = {
@@ -1043,7 +1045,9 @@ void track_paint_util_right_helix_up_small_quarter_tiles_paint(
CoordsXY boundsLength = boundsLengths[direction][index][1];
CoordsXYZ boundsOffset = (boundsOffsets == nullptr ? CoordsXYZ(offset, 0) : boundsOffsets[direction][index][1]);
- PaintAddImageAsParent(session, imageId, { offset, height }, { boundsLength, thickness[1] }, boundsOffset);
+ PaintAddImageAsParent(
+ session, imageId, { offset, height }, { boundsLength, thickness[1] },
+ { boundsOffset.x, boundsOffset.y, height + boundsOffset.z });
}
}
@@ -1480,7 +1484,7 @@ void track_paint_util_right_quarter_turn_5_tiles_paint_2(
const sprite_bb* spriteBB = &sprites[direction][sprite];
const uint32_t imageId = spriteBB->sprite_id | colourFlags;
const auto& offset = spriteBB->offset;
- const auto& bbOffset = spriteBB->offset;
+ const auto& bbOffset = spriteBB->bb_offset;
PaintAddImageAsParent(
session, imageId, { offset.x, offset.y, height + offset.z }, spriteBB->bb_size,
{ bbOffset.x, bbOffset.y, height + bbOffset.z });
@@ -2196,7 +2200,8 @@ void PaintTrack(paint_session* session, Direction direction, int32_t height, con
if (PaintShouldShowHeightMarkers(session, VIEWPORT_FLAG_TRACK_HEIGHTS))
{
session->InteractionType = ViewportInteractionItem::None;
- if (TrackHeightMarkerPositions[trackType] & (1 << trackSequence))
+ const auto& ted = GetTrackElementDescriptor(trackType);
+ if (ted.HeightMarkerPositions & (1 << trackSequence))
{
uint16_t ax = ride->GetRideTypeDescriptor().Heights.VehicleZOffset;
// 0x1689 represents 0 height there are -127 to 128 heights above and below it
diff --git a/src/openrct2/ride/Vehicle.cpp b/src/openrct2/ride/Vehicle.cpp
index bbbdef5358..daa3e934d5 100644
--- a/src/openrct2/ride/Vehicle.cpp
+++ b/src/openrct2/ride/Vehicle.cpp
@@ -50,6 +50,7 @@
#include
#include
+using namespace OpenRCT2::TrackMetaData;
static bool vehicle_boat_is_location_accessible(const CoordsXYZ& location);
constexpr int16_t VEHICLE_MAX_SPIN_SPEED = 1536;
@@ -1522,16 +1523,16 @@ bool Vehicle::OpenRestraints()
}
if (vehicleEntry->animation == VEHICLE_ENTRY_ANIMATION_OBSERVATION_TOWER && vehicle->animation_frame != 0)
{
- if (vehicle->animationState + 0x3333 < 0xFFFF)
+ if (vehicle->animationState <= 0xCCCC)
{
- vehicle->animationState = vehicle->animationState + 0x3333 - 0xFFFF;
- vehicle->animation_frame++;
- vehicle->animation_frame &= 7;
- vehicle->Invalidate();
+ vehicle->animationState += 0x3333;
}
else
{
- vehicle->animationState += 0x3333;
+ vehicle->animationState = 0;
+ vehicle->animation_frame++;
+ vehicle->animation_frame &= 7;
+ vehicle->Invalidate();
}
restraintsOpen = false;
continue;
@@ -1713,7 +1714,8 @@ void Vehicle::UpdateMeasurements()
}
}
- uint16_t trackFlags = TrackFlags[trackElemType];
+ const auto& ted = GetTrackElementDescriptor(trackElemType);
+ uint16_t trackFlags = ted.Flags;
uint32_t testingFlags = curRide->testing_flags;
if (testingFlags & RIDE_TESTING_TURN_LEFT && trackFlags & TRACK_ELEM_FLAG_TURN_LEFT)
@@ -3646,10 +3648,9 @@ void Vehicle::UpdateCollisionSetup()
}
train->IsCrashedVehicle = true;
- train->animationState = scenario_rand();
- train->var_CA = scenario_rand();
+ train->animationState = scenario_rand() & 0xFFFF;
- train->animation_frame = train->var_CA & 0x7;
+ train->animation_frame = scenario_rand() & 0x7;
train->sprite_width = 13;
train->sprite_height_negative = 45;
train->sprite_height_positive = 5;
@@ -5513,14 +5514,18 @@ void Vehicle::UpdateCrash()
ExplosionCloud::Create({ curVehicle->x + xOffset, curVehicle->y + yOffset, curVehicle->z });
}
}
- if (curVehicle->animationState + 7281 > 0xFFFF)
+ if (curVehicle->animationState <= 0xe388)
{
+ curVehicle->animationState += 0x1c71;
+ }
+ else
+ {
+ curVehicle->animationState = 0;
curVehicle->animation_frame++;
if (curVehicle->animation_frame >= 8)
curVehicle->animation_frame = 0;
curVehicle->Invalidate();
}
- curVehicle->animationState += 7281;
continue;
}
@@ -7319,7 +7324,6 @@ void Vehicle::UpdateAdditionalAnimation()
uint8_t curFrame{};
uint32_t eax{};
- uint32_t* curAnimationState = reinterpret_cast(&animationState);
auto vehicleEntry = Entry();
if (vehicleEntry == nullptr)
{
@@ -7328,8 +7332,8 @@ void Vehicle::UpdateAdditionalAnimation()
switch (vehicleEntry->animation)
{
case VEHICLE_ENTRY_ANIMATION_MINITURE_RAILWAY_LOCOMOTIVE: // loc_6D652B
- *curAnimationState += _vehicleVelocityF64E08;
- targetFrame = (*curAnimationState >> 20) & 3;
+ animationState += _vehicleVelocityF64E08;
+ targetFrame = (animationState >> 20) & 3;
if (animation_frame != targetFrame)
{
curFrame = animation_frame;
@@ -7367,8 +7371,8 @@ void Vehicle::UpdateAdditionalAnimation()
}
break;
case VEHICLE_ENTRY_ANIMATION_SWAN: // loc_6D6424
- *curAnimationState += _vehicleVelocityF64E08;
- targetFrame = (*curAnimationState >> 18) & 2;
+ animationState += _vehicleVelocityF64E08;
+ targetFrame = (animationState >> 18) & 2;
if (animation_frame != targetFrame)
{
animation_frame = targetFrame;
@@ -7376,8 +7380,8 @@ void Vehicle::UpdateAdditionalAnimation()
}
break;
case VEHICLE_ENTRY_ANIMATION_CANOES: // loc_6D6482
- *curAnimationState += _vehicleVelocityF64E08;
- eax = ((*curAnimationState >> 13) & 0xFF) * 6;
+ animationState += _vehicleVelocityF64E08;
+ eax = ((animationState >> 13) & 0xFF) * 6;
targetFrame = (eax >> 8) & 0xFF;
if (animation_frame != targetFrame)
{
@@ -7386,8 +7390,8 @@ void Vehicle::UpdateAdditionalAnimation()
}
break;
case VEHICLE_ENTRY_ANIMATION_ROW_BOATS: // loc_6D64F7
- *curAnimationState += _vehicleVelocityF64E08;
- eax = ((*curAnimationState >> 13) & 0xFF) * 7;
+ animationState += _vehicleVelocityF64E08;
+ eax = ((animationState >> 13) & 0xFF) * 7;
targetFrame = (eax >> 8) & 0xFF;
if (animation_frame != targetFrame)
{
@@ -7396,8 +7400,8 @@ void Vehicle::UpdateAdditionalAnimation()
}
break;
case VEHICLE_ENTRY_ANIMATION_WATER_TRICYCLES: // loc_6D6453
- *curAnimationState += _vehicleVelocityF64E08;
- targetFrame = (*curAnimationState >> 19) & 1;
+ animationState += _vehicleVelocityF64E08;
+ targetFrame = (animationState >> 19) & 1;
if (animation_frame != targetFrame)
{
animation_frame = targetFrame;
@@ -7411,15 +7415,15 @@ void Vehicle::UpdateAdditionalAnimation()
}
else
{
- animationState += 0x3333;
+ animationState = 0;
animation_frame += 1;
animation_frame &= 7;
Invalidate();
}
break;
case VEHICLE_ENTRY_ANIMATION_HELICARS: // loc_6D63F5
- *curAnimationState += _vehicleVelocityF64E08;
- targetFrame = (*curAnimationState >> 18) & 3;
+ animationState += _vehicleVelocityF64E08;
+ targetFrame = (animationState >> 18) & 3;
if (animation_frame != targetFrame)
{
animation_frame = targetFrame;
@@ -7429,8 +7433,8 @@ void Vehicle::UpdateAdditionalAnimation()
case VEHICLE_ENTRY_ANIMATION_MONORAIL_CYCLES: // loc_6D64B6
if (num_peeps != 0)
{
- *curAnimationState += _vehicleVelocityF64E08;
- eax = ((*curAnimationState >> 13) & 0xFF) << 2;
+ animationState += _vehicleVelocityF64E08;
+ eax = ((animationState >> 13) & 0xFF) << 2;
targetFrame = (eax >> 8) & 0xFF;
if (animation_frame != targetFrame)
{
@@ -7448,7 +7452,7 @@ void Vehicle::UpdateAdditionalAnimation()
}
else
{
- animationState += 0x3333;
+ animationState = 0;
if (seat_rotation >= target_seat_rotation)
seat_rotation--;
@@ -7465,7 +7469,7 @@ void Vehicle::UpdateAdditionalAnimation()
UpdateAnimationAnimalFlying();
// makes animation play faster with vehicle speed
targetFrame = abs(_vehicleVelocityF64E08) >> 24;
- animationState = std::max(animationState - targetFrame, 0);
+ animationState = std::max(animationState - targetFrame, 0u);
break;
}
}
@@ -7538,12 +7542,13 @@ static void AnimateSceneryDoor(const CoordsXYZD& doorLocation, const CoordsXYZ&
void Vehicle::UpdateSceneryDoor() const
{
auto trackType = GetTrackType();
- const rct_preview_track* trackBlock = TrackBlocks[trackType];
+ const auto& ted = GetTrackElementDescriptor(trackType);
+ const rct_preview_track* trackBlock = ted.Block;
while ((trackBlock + 1)->index != 255)
{
trackBlock++;
}
- const rct_track_coordinates* trackCoordinates = &TrackCoordinates[trackType];
+ const rct_track_coordinates* trackCoordinates = &ted.Coordinates;
auto wallCoords = CoordsXYZ{ x, y, TrackLocation.z - trackBlock->z + trackCoordinates->z_end }.ToTileStart();
int32_t direction = (GetTrackDirection() + trackCoordinates->rotation_end) & 3;
@@ -7635,8 +7640,9 @@ static void trigger_on_ride_photo(const CoordsXYZ& loc, TileElement* tileElement
void Vehicle::UpdateSceneryDoorBackwards() const
{
auto trackType = GetTrackType();
- const rct_preview_track* trackBlock = TrackBlocks[trackType];
- const rct_track_coordinates* trackCoordinates = &TrackCoordinates[trackType];
+ const auto& ted = GetTrackElementDescriptor(trackType);
+ const rct_preview_track* trackBlock = ted.Block;
+ const rct_track_coordinates* trackCoordinates = &ted.Coordinates;
auto wallCoords = CoordsXYZ{ TrackLocation, TrackLocation.z - trackBlock->z + trackCoordinates->z_begin };
int32_t direction = (GetTrackDirection() + trackCoordinates->rotation_begin) & 3;
direction = direction_reverse(direction);
@@ -7974,7 +7980,8 @@ void Vehicle::Sub6DBF3E()
}
auto trackType = GetTrackType();
- if (!(TrackSequenceProperties[trackType][0] & TRACK_SEQUENCE_FLAG_ORIGIN))
+ const auto& ted = GetTrackElementDescriptor(trackType);
+ if (!(ted.SequenceProperties[0] & TRACK_SEQUENCE_FLAG_ORIGIN))
{
return;
}
@@ -8587,7 +8594,8 @@ bool Vehicle::UpdateTrackMotionBackwardsGetNewTrack(uint16_t trackType, Ride* cu
if (next_vehicle_on_train == SPRITE_INDEX_NULL)
{
trackType = tileElement->AsTrack()->GetTrackType();
- if (!(TrackFlags[trackType] & TRACK_ELEM_FLAG_DOWN))
+ const auto& ted = GetTrackElementDescriptor(trackType);
+ if (!(ted.Flags & TRACK_ELEM_FLAG_DOWN))
{
_vehicleMotionTrackFlags |= VEHICLE_UPDATE_MOTION_TRACK_FLAG_9;
}
@@ -9251,7 +9259,8 @@ loc_6DCE02:
}
{
auto trackType = GetTrackType();
- if (!(TrackSequenceProperties[trackType][0] & TRACK_SEQUENCE_FLAG_ORIGIN))
+ const auto& ted = GetTrackElementDescriptor(trackType);
+ if (!(ted.SequenceProperties[0] & TRACK_SEQUENCE_FLAG_ORIGIN))
{
return;
}
diff --git a/src/openrct2/ride/Vehicle.h b/src/openrct2/ride/Vehicle.h
index 8963fb379d..bc04b53ddf 100644
--- a/src/openrct2/ride/Vehicle.h
+++ b/src/openrct2/ride/Vehicle.h
@@ -182,8 +182,7 @@ struct Vehicle : EntityBase
};
uint8_t animation_frame;
uint8_t pad_C6[0x2];
- uint16_t animationState;
- uint16_t var_CA;
+ uint32_t animationState;
OpenRCT2::Audio::SoundId scream_sound_id;
VehicleTrackSubposition TrackSubposition;
union
diff --git a/src/openrct2/scenario/Scenario.h b/src/openrct2/scenario/Scenario.h
index 1477627506..b7de2b2c80 100644
--- a/src/openrct2/scenario/Scenario.h
+++ b/src/openrct2/scenario/Scenario.h
@@ -14,8 +14,6 @@
#include "../management/Finance.h"
#include "../management/Research.h"
#include "../object/Object.h"
-#include "../rct12/RCT12.h"
-#include "../rct2/RCT2.h"
#include "../ride/Ride.h"
#include "../ride/RideRatings.h"
#include "../world/Banner.h"
@@ -26,281 +24,6 @@
using random_engine_t = Random::Rct2::Engine;
-enum class EditorStep : uint8_t;
-
-struct ParkLoadResult;
-
-#pragma pack(push, 1)
-/**
- * SV6/SC6 header chunk
- * size: 0x20
- */
-struct rct_s6_header
-{
- uint8_t type; // 0x00
- uint8_t classic_flag; // 0x01
- uint16_t num_packed_objects; // 0x02
- uint32_t version; // 0x04
- uint32_t magic_number; // 0x08
- uint8_t pad_0C[0x14];
-};
-assert_struct_size(rct_s6_header, 0x20);
-
-/**
- * SC6 information chunk
- * size: 0x198
- */
-struct rct_s6_info
-{
- EditorStep editor_step;
- uint8_t category; // 0x01
- uint8_t objective_type; // 0x02
- uint8_t objective_arg_1; // 0x03
- int32_t objective_arg_2; // 0x04
- int16_t objective_arg_3; // 0x08
- uint8_t pad_00A[0x3E];
- char name[64]; // 0x48
- char details[256]; // 0x88
- rct_object_entry entry; // 0x188
-};
-assert_struct_size(rct_s6_info, 0x198);
-
-enum class ScenarioSource : uint8_t
-{
- RCT1,
- RCT1_AA,
- RCT1_LL,
- RCT2,
- RCT2_WW,
- RCT2_TT,
- Real,
- Other
-};
-
-struct rct_stex_entry
-{
- rct_string_id scenario_name; // 0x00
- rct_string_id park_name; // 0x02
- rct_string_id details; // 0x04
- uint8_t var_06;
-};
-assert_struct_size(rct_stex_entry, 7);
-
-// This will be useful for backwards compatibility
-struct rct_s6_data
-{
- // SC6[0]
- rct_s6_header header;
-
- // SC6[1]
- rct_s6_info info;
-
- // SC6[2]
- // packed objects
-
- // SC6[3]
- rct_object_entry objects[RCT2_OBJECT_ENTRY_COUNT];
-
- // SC6[4]
- uint16_t elapsed_months;
- uint16_t current_day;
- uint32_t scenario_ticks;
- uint32_t scenario_srand_0;
- uint32_t scenario_srand_1;
-
- // SC6[5]
- RCT12TileElement tile_elements[RCT2_MAX_TILE_ELEMENTS];
-
- // SC6[6]
- uint32_t next_free_tile_element_pointer_index;
- RCT2Sprite sprites[RCT2_MAX_SPRITES];
- uint16_t sprite_lists_head[static_cast(EntityListId::Count)];
- uint16_t sprite_lists_count[static_cast(EntityListId::Count)];
- rct_string_id park_name;
- uint8_t pad_013573D6[2];
- uint32_t park_name_args;
- money32 initial_cash;
- money32 current_loan;
- uint32_t park_flags;
- money16 park_entrance_fee;
- uint16_t rct1_park_entrance_x;
- uint16_t rct1_park_entrance_y;
- uint8_t pad_013573EE[2];
- uint8_t rct1_park_entrance_z;
- uint8_t pad_013573F1;
- rct12_peep_spawn peep_spawns[RCT12_MAX_PEEP_SPAWNS];
- uint8_t guest_count_change_modifier;
- uint8_t current_research_level;
- uint8_t pad_01357400[4];
- uint32_t researched_ride_types[RCT2_MAX_RESEARCHED_RIDE_TYPE_QUADS];
- uint32_t researched_ride_entries[RCT2_MAX_RESEARCHED_RIDE_ENTRY_QUADS];
- uint32_t researched_track_types_a[128];
- uint32_t researched_track_types_b[128];
-
- // SC6[7]
- uint16_t guests_in_park;
- uint16_t guests_heading_for_park;
-
- // Ignored in scenario
- money32 expenditure_table[RCT12_EXPENDITURE_TABLE_MONTH_COUNT][RCT12_EXPENDITURE_TYPE_COUNT];
-
- // SC6[8]
- uint16_t last_guests_in_park;
- uint8_t pad_01357BCA[3];
- uint8_t handyman_colour;
- uint8_t mechanic_colour;
- uint8_t security_colour;
-
- // Ignored in scenario
- uint32_t researched_scenery_items[RCT2_MAX_RESEARCHED_SCENERY_ITEM_QUADS];
-
- // SC6[9]
- uint16_t park_rating;
-
- // Ignored in scenario
- uint8_t park_rating_history[32];
- uint8_t guests_in_park_history[32];
-
- // SC6[10]
- uint8_t active_research_types;
- uint8_t research_progress_stage;
- uint32_t last_researched_item_subject;
- uint8_t pad_01357CF8[1000];
- uint32_t next_research_item;
- uint16_t research_progress;
- uint8_t next_research_category;
- uint8_t next_research_expected_day;
- uint8_t next_research_expected_month;
- uint8_t guest_initial_happiness;
- uint16_t park_size;
- uint16_t guest_generation_probability;
- uint16_t total_ride_value_for_money;
- money32 maximum_loan;
- money16 guest_initial_cash;
- uint8_t guest_initial_hunger;
- uint8_t guest_initial_thirst;
- uint8_t objective_type;
- uint8_t objective_year;
- uint8_t pad_013580FA[2];
- money32 objective_currency;
- uint16_t objective_guests;
- uint8_t campaign_weeks_left[20];
- uint8_t campaign_ride_index[22];
-
- // Ignored in scenario
- money32 balance_history[RCT12_FINANCE_GRAPH_SIZE];
-
- // SC6[11]
- money32 current_expenditure;
- money32 current_profit;
- money32 weekly_profit_average_dividend;
- uint16_t weekly_profit_average_divisor;
- uint8_t pad_0135833A[2];
-
- // Ignored in scenario
- money32 weekly_profit_history[RCT12_FINANCE_GRAPH_SIZE];
-
- // SC6[12]
- money32 park_value;
-
- // Ignored in scenario
- money32 park_value_history[RCT12_FINANCE_GRAPH_SIZE];
-
- // SC6[13]
- money32 completed_company_value;
- uint32_t total_admissions;
- money32 income_from_admissions;
- money32 company_value;
- uint8_t peep_warning_throttle[16];
- rct12_award awards[RCT12_MAX_AWARDS];
- money16 land_price;
- money16 construction_rights_price;
- uint16_t word_01358774;
- uint8_t pad_01358776[2];
- uint32_t cd_key;
- uint8_t pad_0135877C[64];
- uint32_t game_version_number;
- money32 completed_company_value_record;
- uint32_t loan_hash;
- uint16_t ride_count;
- uint8_t pad_013587CA[6];
- money32 historical_profit;
- uint8_t pad_013587D4[4];
- char scenario_completed_name[32];
- money32 cash;
- uint8_t pad_013587FC[50];
- uint16_t park_rating_casualty_penalty;
- uint16_t map_size_units;
- uint16_t map_size_minus_2;
- uint16_t map_size;
- uint16_t map_max_xy;
- uint32_t same_price_throughout;
- uint16_t suggested_max_guests;
- uint16_t park_rating_warning_days;
- uint8_t last_entrance_style;
- uint8_t rct1_water_colour;
- uint8_t pad_01358842[2];
- RCT12ResearchItem research_items[MAX_RESEARCH_ITEMS];
- uint16_t map_base_z;
- char scenario_name[64];
- char scenario_description[256];
- uint8_t current_interest_rate;
- uint8_t pad_0135934B;
- uint32_t same_price_throughout_extended;
- int16_t park_entrance_x[RCT12_MAX_PARK_ENTRANCES];
- int16_t park_entrance_y[RCT12_MAX_PARK_ENTRANCES];
- int16_t park_entrance_z[RCT12_MAX_PARK_ENTRANCES];
- uint8_t park_entrance_direction[RCT12_MAX_PARK_ENTRANCES];
- char scenario_filename[256];
- uint8_t saved_expansion_pack_names[3256];
- RCT12Banner banners[RCT2_MAX_BANNERS_IN_PARK];
- char custom_strings[RCT12_MAX_USER_STRINGS][RCT12_USER_STRING_MAX_LENGTH];
- uint32_t game_ticks_1;
- rct2_ride rides[RCT12_MAX_RIDES_IN_PARK];
- uint16_t saved_age;
- int16_t saved_view_x;
- int16_t saved_view_y;
- uint8_t saved_view_zoom;
- uint8_t saved_view_rotation;
- RCT12MapAnimation map_animations[RCT2_MAX_ANIMATED_OBJECTS];
- uint16_t num_map_animations;
- uint8_t pad_0138B582[2];
- RCT2RideRatingCalculationData ride_ratings_calc_data;
- uint8_t pad_0138B5D0[60];
- RCT12RideMeasurement ride_measurements[8];
- uint32_t next_guest_index;
- uint16_t grass_and_scenery_tilepos;
- uint32_t patrol_areas[(RCT2_MAX_STAFF + RCT12_STAFF_TYPE_COUNT) * RCT12_PATROL_AREA_SIZE];
- uint8_t staff_modes[RCT2_MAX_STAFF + RCT12_STAFF_TYPE_COUNT];
- uint8_t pad_13CA73E;
- uint8_t pad_13CA73F;
- uint8_t byte_13CA740;
- uint8_t pad_13CA741;
- uint8_t byte_13CA742[4]; // unused
- uint8_t climate;
- uint8_t pad_013CA747;
- uint16_t climate_update_timer;
- uint8_t current_weather;
- uint8_t next_weather;
- uint8_t temperature;
- uint8_t next_temperature;
- uint8_t current_weather_effect;
- uint8_t next_weather_effect;
- uint8_t current_weather_gloom;
- uint8_t next_weather_gloom;
- uint8_t current_weather_level;
- uint8_t next_weather_level;
- rct12_news_item news_items[RCT12_MAX_NEWS_ITEMS];
- char rct1_scenario_name[62]; // Unused in RCT2
- uint16_t rct1_scenario_slot_index; // Unused in RCT2
- uint32_t rct1_scenario_flags; // Unused in RCT2
- uint16_t wide_path_tile_loop_x;
- uint16_t wide_path_tile_loop_y;
- uint8_t pad_13CE778[434];
-};
-assert_struct_size(rct_s6_data, 0x46b44a);
-#pragma pack(pop)
-
enum
{
SCENARIO_FLAGS_VISIBLE = (1 << 0),
diff --git a/src/openrct2/scenario/ScenarioRepository.h b/src/openrct2/scenario/ScenarioRepository.h
index 8d6898d464..c9ff1e12c7 100644
--- a/src/openrct2/scenario/ScenarioRepository.h
+++ b/src/openrct2/scenario/ScenarioRepository.h
@@ -24,6 +24,18 @@ struct scenario_highscore_entry
datetime64 timestamp;
};
+enum class ScenarioSource : uint8_t
+{
+ RCT1,
+ RCT1_AA,
+ RCT1_LL,
+ RCT2,
+ RCT2_WW,
+ RCT2_TT,
+ Real,
+ Other
+};
+
struct scenario_index_entry
{
utf8 path[MAX_PATH];
diff --git a/src/openrct2/scenario/ScenarioSources.cpp b/src/openrct2/scenario/ScenarioSources.cpp
index 38f50f4c5a..584a1517b8 100644
--- a/src/openrct2/scenario/ScenarioSources.cpp
+++ b/src/openrct2/scenario/ScenarioSources.cpp
@@ -12,6 +12,7 @@
#include "../core/Guard.hpp"
#include "../core/String.hpp"
#include "Scenario.h"
+#include "ScenarioRepository.h"
#include
diff --git a/src/openrct2/title/TitleScreen.cpp b/src/openrct2/title/TitleScreen.cpp
index f267ae4891..02e134ef8f 100644
--- a/src/openrct2/title/TitleScreen.cpp
+++ b/src/openrct2/title/TitleScreen.cpp
@@ -23,6 +23,7 @@
#include "../interface/Viewport.h"
#include "../interface/Window.h"
#include "../localisation/Localisation.h"
+#include "../network/NetworkBase.h"
#include "../network/network.h"
#include "../scenario/Scenario.h"
#include "../scenario/ScenarioRepository.h"
@@ -124,7 +125,9 @@ void TitleScreen::Load()
gScreenAge = 0;
gCurrentLoadedPath = "";
- network_close();
+#ifndef DISABLE_NETWORK
+ GetContext()->GetNetwork().Close();
+#endif
OpenRCT2::Audio::StopAll();
GetContext()->GetGameState()->InitAll(150);
viewport_init_all();
diff --git a/src/openrct2/windows/_legacy.cpp b/src/openrct2/windows/_legacy.cpp
index bfbcb7da71..2fb047ac62 100644
--- a/src/openrct2/windows/_legacy.cpp
+++ b/src/openrct2/windows/_legacy.cpp
@@ -27,6 +27,7 @@
#include
#include
+using namespace OpenRCT2::TrackMetaData;
bool gDisableErrorWindowSound = false;
uint64_t _enabledRidePieces;
@@ -90,7 +91,8 @@ money32 place_provisional_track_piece(
return result;
int16_t z_begin, z_end;
- const rct_track_coordinates& coords = TrackCoordinates[trackType];
+ const auto& ted = GetTrackElementDescriptor(trackType);
+ const rct_track_coordinates& coords = ted.Coordinates;
if (!ride->GetRideTypeDescriptor().HasFlag(RIDE_TYPE_FLAG_HAS_NO_TRACK))
{
z_begin = coords.z_begin;
@@ -304,7 +306,8 @@ bool window_ride_construction_update_state(
&& _currentTrackAlternative & RIDE_TYPE_ALTERNATIVE_TRACK_PIECES)
{
auto availablePieces = rtd.CoveredTrackPieces;
- auto alternativeType = AlternativeTrackTypes[trackType];
+ const auto& ted = GetTrackElementDescriptor(trackType);
+ auto alternativeType = ted.AlternativeType;
if (alternativeType != TrackElemType::None && (availablePieces & (1ULL << trackType)))
{
trackType = alternativeType;
@@ -312,7 +315,8 @@ bool window_ride_construction_update_state(
}
}
- const rct_track_coordinates& trackCoordinates = TrackCoordinates[trackType];
+ const auto& ted = GetTrackElementDescriptor(trackType);
+ const rct_track_coordinates& trackCoordinates = ted.Coordinates;
x = _currentTrackBegin.x;
y = _currentTrackBegin.y;
@@ -345,13 +349,13 @@ bool window_ride_construction_update_state(
bool turnOffLiftHill = false;
if (!(_enabledRidePieces & (1ULL << TRACK_LIFT_HILL_CURVE)))
{
- if (TrackFlags[trackType] & TRACK_ELEM_FLAG_CURVE_ALLOWS_LIFT)
+ if (ted.Flags & TRACK_ELEM_FLAG_CURVE_ALLOWS_LIFT)
{
turnOffLiftHill = true;
}
}
- if (!(TrackFlags[trackType] & TRACK_ELEM_FLAG_ALLOW_LIFT_HILL))
+ if (!(ted.Flags & TRACK_ELEM_FLAG_ALLOW_LIFT_HILL))
{
turnOffLiftHill = true;
}
diff --git a/src/openrct2/world/Banner.cpp b/src/openrct2/world/Banner.cpp
index f51937f5bf..1d276df688 100644
--- a/src/openrct2/world/Banner.cpp
+++ b/src/openrct2/world/Banner.cpp
@@ -21,6 +21,7 @@
#include "../ride/RideData.h"
#include "../ride/Track.h"
#include "../windows/Intent.h"
+#include "../world/TileElementsView.h"
#include "Map.h"
#include "MapAnimation.h"
#include "Park.h"
@@ -253,57 +254,50 @@ void fix_duplicated_banners()
{
// For each banner in the map, check if the banner index is in use already, and if so, create a new entry for it
std::vector activeBanners;
+ activeBanners.resize(MAX_BANNERS);
+
for (int y = 0; y < MAXIMUM_MAP_SIZE_TECHNICAL; y++)
{
for (int x = 0; x < MAXIMUM_MAP_SIZE_TECHNICAL; x++)
{
- auto tileElement = map_get_first_element_at(TileCoordsXY{ x, y }.ToCoordsXY());
- if (tileElement != nullptr)
+ const auto bannerPos = TileCoordsXY{ x, y }.ToCoordsXY();
+ for (auto* bannerElement : OpenRCT2::TileElementsView(bannerPos))
{
- do
+ auto bannerIndex = bannerElement->GetIndex();
+ if (bannerIndex == BANNER_INDEX_NULL)
+ continue;
+
+ if (activeBanners[bannerIndex])
{
- // TODO: Handle walls and large-scenery that use banner indices too. Large scenery can be tricky, as they
- // occupy multiple tiles that should both refer to the same banner index.
- if (tileElement->GetType() == TILE_ELEMENT_TYPE_BANNER)
+ log_info(
+ "Duplicated banner with index %d found at x = %d, y = %d and z = %d.", bannerIndex, x, y,
+ bannerElement->base_height);
+
+ // Banner index is already in use by another banner, so duplicate it
+ auto newBanner = CreateBanner();
+ if (newBanner == nullptr)
{
- auto bannerIndex = tileElement->AsBanner()->GetIndex();
- if (bannerIndex == BANNER_INDEX_NULL)
- continue;
-
- if (activeBanners.size() <= bannerIndex)
- {
- activeBanners.resize(bannerIndex + 1);
- }
- if (activeBanners[bannerIndex])
- {
- log_info(
- "Duplicated banner with index %d found at x = %d, y = %d and z = %d.", bannerIndex, x, y,
- tileElement->base_height);
-
- // Banner index is already in use by another banner, so duplicate it
- auto newBanner = CreateBanner();
- if (newBanner == nullptr)
- {
- log_error("Failed to create new banner.");
- continue;
- }
- Guard::Assert(!activeBanners[newBanner->id]);
-
- // Copy over the original banner, but update the location
- auto oldBanner = GetBanner(bannerIndex);
- if (oldBanner != nullptr)
- {
- *newBanner = *oldBanner;
- newBanner->position = { x, y };
- }
-
- tileElement->AsBanner()->SetIndex(newBanner->id);
- }
-
- // Mark banner index as in-use
- activeBanners[bannerIndex] = true;
+ log_error("Failed to create new banner.");
+ continue;
}
- } while (!(tileElement++)->IsLastForTile());
+ Guard::Assert(!activeBanners[newBanner->id]);
+
+ // Copy over the original banner, but update the location
+ const auto* oldBanner = GetBanner(bannerIndex);
+ if (oldBanner != nullptr)
+ {
+ auto newBannerId = newBanner->id;
+
+ *newBanner = *oldBanner;
+ newBanner->id = newBannerId;
+ newBanner->position = { x, y };
+ }
+
+ bannerElement->SetIndex(newBanner->id);
+ }
+
+ // Mark banner index as in-use
+ activeBanners[bannerIndex] = true;
}
}
}
diff --git a/src/openrct2/world/Entity.cpp b/src/openrct2/world/Entity.cpp
index bc1b1e0859..7d45216925 100644
--- a/src/openrct2/world/Entity.cpp
+++ b/src/openrct2/world/Entity.cpp
@@ -279,7 +279,6 @@ void Vehicle::Serialise(DataSerialiser& stream)
stream << dodgems_collision_direction;
stream << animation_frame;
stream << animationState;
- stream << var_CA;
stream << scream_sound_id;
stream << TrackSubposition;
stream << var_CE;
diff --git a/src/openrct2/world/Footpath.cpp b/src/openrct2/world/Footpath.cpp
index d45644ca62..4290b59ebf 100644
--- a/src/openrct2/world/Footpath.cpp
+++ b/src/openrct2/world/Footpath.cpp
@@ -40,6 +40,7 @@
#include
#include
+using namespace OpenRCT2::TrackMetaData;
void footpath_update_queue_entrance_banner(const CoordsXY& footpathPos, TileElement* tileElement);
FootpathSelection gFootpathSelection;
@@ -887,13 +888,15 @@ static void loc_6A6D7E(
const auto trackType = tileElement->AsTrack()->GetTrackType();
const uint8_t trackSequence = tileElement->AsTrack()->GetSequenceIndex();
- if (!(TrackSequenceProperties[trackType][trackSequence] & TRACK_SEQUENCE_FLAG_CONNECTS_TO_PATH))
+ const auto& ted = GetTrackElementDescriptor(trackType);
+ if (!(ted.SequenceProperties[trackSequence] & TRACK_SEQUENCE_FLAG_CONNECTS_TO_PATH))
{
return;
}
uint16_t dx = direction_reverse(
(direction - tileElement->GetDirection()) & TILE_ELEMENT_DIRECTION_MASK);
- if (!(TrackSequenceProperties[trackType][trackSequence] & (1 << dx)))
+
+ if (!(ted.SequenceProperties[trackSequence] & (1 << dx)))
{
return;
}
@@ -969,12 +972,13 @@ static void loc_6A6C85(
const auto trackType = tileElementPos.element->AsTrack()->GetTrackType();
const uint8_t trackSequence = tileElementPos.element->AsTrack()->GetSequenceIndex();
- if (!(TrackSequenceProperties[trackType][trackSequence] & TRACK_SEQUENCE_FLAG_CONNECTS_TO_PATH))
+ const auto& ted = GetTrackElementDescriptor(trackType);
+ if (!(ted.SequenceProperties[trackSequence] & TRACK_SEQUENCE_FLAG_CONNECTS_TO_PATH))
{
return;
}
uint16_t dx = (direction - tileElementPos.element->GetDirection()) & TILE_ELEMENT_DIRECTION_MASK;
- if (!(TrackSequenceProperties[trackType][trackSequence] & (1 << dx)))
+ if (!(ted.SequenceProperties[trackSequence] & (1 << dx)))
{
return;
}
@@ -2139,10 +2143,11 @@ bool tile_element_wants_path_connection_towards(const TileCoordsXYZD& coords, co
const auto trackType = tileElement->AsTrack()->GetTrackType();
const uint8_t trackSequence = tileElement->AsTrack()->GetSequenceIndex();
- if (TrackSequenceProperties[trackType][trackSequence] & TRACK_SEQUENCE_FLAG_CONNECTS_TO_PATH)
+ const auto& ted = GetTrackElementDescriptor(trackType);
+ if (ted.SequenceProperties[trackSequence] & TRACK_SEQUENCE_FLAG_CONNECTS_TO_PATH)
{
uint16_t dx = ((coords.direction - tileElement->GetDirection()) & TILE_ELEMENT_DIRECTION_MASK);
- if (TrackSequenceProperties[trackType][trackSequence] & (1 << dx))
+ if (ted.SequenceProperties[trackSequence] & (1 << dx))
{
// Track element has the flags required for the given direction
return true;
diff --git a/src/openrct2/world/TileInspector.cpp b/src/openrct2/world/TileInspector.cpp
index 3765e56f7c..5359464465 100644
--- a/src/openrct2/world/TileInspector.cpp
+++ b/src/openrct2/world/TileInspector.cpp
@@ -37,6 +37,7 @@ TileCoordsXY windowTileInspectorTile;
int32_t windowTileInspectorElementCount = 0;
int32_t windowTileInspectorSelectedIndex;
+using namespace OpenRCT2::TrackMetaData;
namespace OpenRCT2::TileInspector
{
static bool SwapTileElements(const CoordsXY& loc, int16_t first, int16_t second)
@@ -811,7 +812,8 @@ namespace OpenRCT2::TileInspector
if (ride == nullptr)
return std::make_unique(GameActions::Status::Unknown, STR_NONE);
- auto trackBlock = TrackBlocks[type];
+ const auto& ted = GetTrackElementDescriptor(type);
+ const auto* trackBlock = ted.Block;
trackBlock += trackElement->AsTrack()->GetSequenceIndex();
uint8_t originDirection = trackElement->GetDirection();
@@ -823,7 +825,7 @@ namespace OpenRCT2::TileInspector
originY = static_cast(coords.y);
originZ -= trackBlock->z;
- trackBlock = TrackBlocks[type];
+ trackBlock = ted.Block;
for (; trackBlock->index != 255; trackBlock++)
{
CoordsXYZD elem = { originX, originY, originZ + trackBlock->z, rotation };
@@ -894,7 +896,8 @@ namespace OpenRCT2::TileInspector
if (ride == nullptr)
return std::make_unique(GameActions::Status::Unknown, STR_NONE);
- auto trackBlock = TrackBlocks[type];
+ const auto& ted = GetTrackElementDescriptor(type);
+ auto trackBlock = ted.Block;
trackBlock += trackElement->AsTrack()->GetSequenceIndex();
uint8_t originDirection = trackElement->GetDirection();
@@ -906,7 +909,7 @@ namespace OpenRCT2::TileInspector
originY = static_cast(coords.y);
originZ -= trackBlock->z;
- trackBlock = TrackBlocks[type];
+ trackBlock = ted.Block;
for (; trackBlock->index != 255; trackBlock++)
{
CoordsXYZD elem = { originX, originY, originZ + trackBlock->z, rotation };