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 };