From 1fa2fa8f80fba8e4a90f52828d7d2da9f53af15a Mon Sep 17 00:00:00 2001 From: Michael Steenbeek Date: Wed, 7 Mar 2018 19:10:50 +0100 Subject: [PATCH] Refactor ride->entrances and ride->exits --- OpenRCT2.xcodeproj/project.pbxproj | 5 +- src/openrct2-ui/windows/Ride.cpp | 7 +- src/openrct2/Game.cpp | 3 - src/openrct2/actions/RideCreateAction.hpp | 6 +- src/openrct2/network/Network.cpp | 2 +- src/openrct2/peep/Peep.cpp | 124 ++++----- src/openrct2/peep/Staff.cpp | 17 +- src/openrct2/rct1/S4Importer.cpp | 18 +- src/openrct2/rct2/S6Exporter.cpp | 16 +- src/openrct2/rct2/S6Importer.cpp | 19 +- src/openrct2/ride/Ride.cpp | 256 ++++++++++-------- src/openrct2/ride/Ride.h | 6 +- src/openrct2/ride/RideRatings.cpp | 24 +- src/openrct2/ride/Station.cpp | 90 +++--- src/openrct2/ride/Station.h | 11 +- src/openrct2/ride/TrackDesignSave.cpp | 22 +- src/openrct2/ride/TrackPaint.cpp | 9 +- src/openrct2/ride/Vehicle.cpp | 14 +- src/openrct2/world/Entrance.cpp | 43 +-- src/openrct2/world/Entrance.h | 2 +- src/openrct2/world/Footpath.cpp | 9 +- .../world/{Location.h => Location.hpp} | 7 + src/openrct2/world/Map.h | 2 +- src/openrct2/world/TileInspector.cpp | 59 +++- test/testpaint/Compat.cpp | 13 + 25 files changed, 453 insertions(+), 331 deletions(-) rename src/openrct2/world/{Location.h => Location.hpp} (92%) diff --git a/OpenRCT2.xcodeproj/project.pbxproj b/OpenRCT2.xcodeproj/project.pbxproj index 400550c7fe..8b497c839a 100644 --- a/OpenRCT2.xcodeproj/project.pbxproj +++ b/OpenRCT2.xcodeproj/project.pbxproj @@ -702,7 +702,6 @@ 4C7B54282007646A00A52E21 /* Fountain.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Fountain.h; sourceTree = ""; }; 4C7B54292007646A00A52E21 /* LargeScenery.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LargeScenery.cpp; sourceTree = ""; }; 4C7B542A2007646A00A52E21 /* LargeScenery.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LargeScenery.h; sourceTree = ""; }; - 4C7B542B2007646A00A52E21 /* Location.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Location.h; sourceTree = ""; }; 4C7B542C2007646A00A52E21 /* Map.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Map.cpp; sourceTree = ""; }; 4C7B542D2007646A00A52E21 /* Map.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Map.h; sourceTree = ""; }; 4C7B542E2007646A00A52E21 /* MapAnimation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MapAnimation.cpp; sourceTree = ""; }; @@ -738,6 +737,7 @@ 4C8B426E1EEB1ABD00F015CA /* X8DrawingEngine.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = X8DrawingEngine.cpp; sourceTree = ""; }; 4C8B426F1EEB1ABD00F015CA /* X8DrawingEngine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = X8DrawingEngine.h; sourceTree = ""; }; 4C8B42711EEB1AE400F015CA /* HardwareDisplayDrawingEngine.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HardwareDisplayDrawingEngine.cpp; sourceTree = ""; }; + 4C9196ED204FF3E000869A24 /* Location.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Location.hpp; sourceTree = ""; }; 4C93F1181F8B744400A9330D /* AirPoweredVerticalCoaster.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AirPoweredVerticalCoaster.cpp; sourceTree = ""; }; 4C93F1191F8B744400A9330D /* BobsleighCoaster.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BobsleighCoaster.cpp; sourceTree = ""; }; 4C93F11A1F8B744400A9330D /* BolligerMabillardTrack.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BolligerMabillardTrack.h; sourceTree = ""; }; @@ -2444,7 +2444,7 @@ 4C7B54282007646A00A52E21 /* Fountain.h */, 4C7B54292007646A00A52E21 /* LargeScenery.cpp */, 4C7B542A2007646A00A52E21 /* LargeScenery.h */, - 4C7B542B2007646A00A52E21 /* Location.h */, + 4C9196ED204FF3E000869A24 /* Location.hpp */, 4C7B542C2007646A00A52E21 /* Map.cpp */, 4C7B542D2007646A00A52E21 /* Map.h */, 4C7B542E2007646A00A52E21 /* MapAnimation.cpp */, @@ -2983,7 +2983,6 @@ C68313C81FDB4ED4006DB3D8 /* MouseInput.cpp in Sources */, C68878C920289B710084B384 /* TextureCache.cpp in Sources */, C61ADB1F1FB6A0A70024F2EF /* TopToolbar.cpp in Sources */, - F7C44AF72030E74B007E099F /* AVX2Drawing.cpp in Sources */, F76C887B1EC5324E00FA49E2 /* FileAudioSource.cpp in Sources */, C68878CA20289B710084B384 /* TransparencyDepth.cpp in Sources */, C64644FD1F3FA4120026AC2D /* Land.cpp in Sources */, diff --git a/src/openrct2-ui/windows/Ride.cpp b/src/openrct2-ui/windows/Ride.cpp index 9e8cabfcb9..b6c5d29d4a 100644 --- a/src/openrct2-ui/windows/Ride.cpp +++ b/src/openrct2-ui/windows/Ride.cpp @@ -45,6 +45,7 @@ #include #include #include +#include enum { WINDOW_RIDE_PAGE_MAIN, @@ -2535,12 +2536,12 @@ static rct_string_id window_ride_get_status_station(rct_window *w, void *argumen // Entrance / exit if (ride->status == RIDE_STATUS_CLOSED) { - if (ride->entrances[stationIndex].xy == RCT_XY8_UNDEFINED) + if (ride_get_entrance_location((uint8)w->number, (uint8)stationIndex).isNull()) stringId = STR_NO_ENTRANCE; - else if (ride->exits[stationIndex].xy == RCT_XY8_UNDEFINED) + else if (ride_get_exit_location((uint8)w->number, (uint8)stationIndex).isNull()) stringId = STR_NO_EXIT; } else { - if (ride->entrances[stationIndex].xy == RCT_XY8_UNDEFINED) + if (ride_get_entrance_location((uint8)w->number, (uint8)stationIndex).isNull()) stringId = STR_EXIT_ONLY; } diff --git a/src/openrct2/Game.cpp b/src/openrct2/Game.cpp index 6b39a67153..bd5a70a7e6 100644 --- a/src/openrct2/Game.cpp +++ b/src/openrct2/Game.cpp @@ -1296,9 +1296,6 @@ void game_fix_save_vars() // Fix gParkEntrance locations for which the tile_element no longer exists fix_park_entrance_locations(); - - // Fix ride entrances and exits that were moved without updating ride->entrances[] / ride->exits[] - fix_ride_entrance_and_exit_locations(); } void handle_park_load_failure_with_title_opt(const ParkLoadResult * result, const std::string & path, bool loadTitleFirst) diff --git a/src/openrct2/actions/RideCreateAction.hpp b/src/openrct2/actions/RideCreateAction.hpp index 29537edfdf..68daef5b9d 100644 --- a/src/openrct2/actions/RideCreateAction.hpp +++ b/src/openrct2/actions/RideCreateAction.hpp @@ -145,11 +145,11 @@ public: ride_set_name_to_default(ride, rideEntry); } - for (size_t i = 0; i < MAX_STATIONS; i++) + for (sint32 i = 0; i < MAX_STATIONS; i++) { ride->station_starts[i].xy = RCT_XY8_UNDEFINED; - ride->entrances[i].xy = RCT_XY8_UNDEFINED; - ride->exits[i].xy = RCT_XY8_UNDEFINED; + ride_clear_entrance_location(ride, i); + ride_clear_exit_location(ride, i); ride->train_at_station[i] = 255; ride->queue_time[i] = 0; } diff --git a/src/openrct2/network/Network.cpp b/src/openrct2/network/Network.cpp index ea141b2961..f4eb2135a0 100644 --- a/src/openrct2/network/Network.cpp +++ b/src/openrct2/network/Network.cpp @@ -33,7 +33,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 "36" +#define NETWORK_STREAM_VERSION "37" #define NETWORK_STREAM_ID OPENRCT2_VERSION "-" NETWORK_STREAM_VERSION static rct_peep* _pickup_peep = nullptr; diff --git a/src/openrct2/peep/Peep.cpp b/src/openrct2/peep/Peep.cpp index 52dd10e661..af731d9cac 100644 --- a/src/openrct2/peep/Peep.cpp +++ b/src/openrct2/peep/Peep.cpp @@ -2617,8 +2617,8 @@ static void peep_choose_seat_from_car(rct_peep * peep, Ride * ride, rct_vehicle */ static void peep_go_to_ride_entrance(rct_peep * peep, Ride * ride) { - TileCoordsXYZD location = ride_get_entrance_location_of_station(peep->current_ride, peep->current_ride_station); - Guard::Assert(location.x != LOCATION_NULL); + TileCoordsXYZD location = ride_get_entrance_location(peep->current_ride, peep->current_ride_station); + Guard::Assert(!location.isNull()); sint32 x = location.x; sint32 y = location.y; @@ -2683,7 +2683,8 @@ static void peep_update_ride_sub_state_0(rct_peep * peep) sint16 z = peep->z; if (xy_distance < 16) { - z = ride->station_heights[peep->current_ride_station] * 8 + 2; + auto entrance = ride_get_entrance_location(ride, peep->current_ride_station); + z = entrance.z * 8 + 2; } sprite_move(x, y, z, (rct_sprite *)peep); invalidate_sprite_2((rct_sprite *)peep); @@ -2906,8 +2907,8 @@ static void peep_update_ride_sub_state_1(rct_peep * peep) if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_NO_VEHICLES)) { - TileCoordsXYZD entranceLocation = ride_get_entrance_location_of_station(peep->current_ride, peep->current_ride_station); - Guard::Assert(entranceLocation.x != LOCATION_NULL); + TileCoordsXYZD entranceLocation = ride_get_entrance_location(peep->current_ride, peep->current_ride_station); + Guard::Assert(!entranceLocation.isNull()); x = entranceLocation.x; y = entranceLocation.y; @@ -2991,7 +2992,7 @@ static void peep_update_ride_sub_state_1(rct_peep * peep) if (vehicle_type->flags & VEHICLE_ENTRY_FLAG_26) { - TileCoordsXYZD entranceLocation = ride_get_entrance_location_of_station(peep->current_ride, peep->current_ride_station); + TileCoordsXYZD entranceLocation = ride_get_entrance_location(peep->current_ride, peep->current_ride_station); uint8 direction_entrance = entranceLocation.direction; x = ride->station_starts[peep->current_ride_station].x; @@ -3094,9 +3095,11 @@ static void peep_go_to_ride_exit(rct_peep * peep, Ride * ride, sint16 x, sint16 sprite_move(x, y, z, (rct_sprite *)peep); invalidate_sprite_2((rct_sprite *)peep); - assert(peep->current_ride_station < MAX_STATIONS); - x = ride->exits[peep->current_ride_station].x; - y = ride->exits[peep->current_ride_station].y; + Guard::Assert(peep->current_ride_station < MAX_STATIONS); + auto exit = ride_get_exit_location(ride, peep->current_ride_station); + Guard::Assert(!exit.isNull()); + x = exit.x; + y = exit.y; x *= 32; y *= 32; x += 16; @@ -3202,7 +3205,7 @@ static void peep_update_ride_sub_state_2_enter_ride(rct_peep * peep, Ride * ride */ static void peep_update_ride_sub_state_2_rejoin_queue(rct_peep * peep, Ride * ride) { - TileCoordsXYZD entranceLocation = ride_get_entrance_location_of_station(peep->current_ride, peep->current_ride_station); + TileCoordsXYZD entranceLocation = ride_get_entrance_location(peep->current_ride, peep->current_ride_station); sint32 x = entranceLocation.x * 32; sint32 y = entranceLocation.y * 32; @@ -3435,7 +3438,7 @@ static void peep_update_ride_sub_state_7(rct_peep * peep) if (!(vehicle_entry->flags & VEHICLE_ENTRY_FLAG_26)) { assert(peep->current_ride_station < MAX_STATIONS); - TileCoordsXYZD exitLocation = ride_get_exit_location_of_station(peep->current_ride, peep->current_ride_station); + TileCoordsXYZD exitLocation = ride_get_exit_location(peep->current_ride, peep->current_ride_station); sint32 x, y; sint32 z = ride->station_heights[peep->current_ride_station]; @@ -3527,8 +3530,8 @@ static void peep_update_ride_sub_state_7(rct_peep * peep) return; } - TileCoordsXYZD exitLocation = ride_get_exit_location_of_station(peep->current_ride, peep->current_ride_station); - Guard::Assert(exitLocation.x != LOCATION_NULL); + TileCoordsXYZD exitLocation = ride_get_exit_location(peep->current_ride, peep->current_ride_station); + Guard::Assert(!exitLocation.isNull()); sint16 z = (sint16)exitLocation.z; uint8 exit_direction = exitLocation.direction; @@ -3603,13 +3606,10 @@ static void peep_update_ride_prepare_for_state_9(rct_peep * peep) Ride * ride = get_ride(peep->current_ride); Guard::Assert(peep->current_ride_station < Util::CountOf(ride->exits), GUARD_LINE); - sint16 x = ride->exits[peep->current_ride_station].x; - sint16 y = ride->exits[peep->current_ride_station].y; - sint16 z = ride->station_heights[peep->current_ride_station]; - - rct_tile_element * tile_element = ride_get_station_exit_element(ride, x, y, z); - - uint8 exit_direction = (tile_element == nullptr ? 0 : tile_element_get_direction(tile_element)); + auto exit = ride_get_exit_location(peep->current_ride, peep->current_ride_station); + sint16 x = exit.x; + sint16 y = exit.y; + uint8 exit_direction = exit.direction; x *= 32; y *= 32; @@ -3850,14 +3850,10 @@ static void peep_update_ride_sub_state_13(rct_peep * peep) peep->var_37 |= 3; - x = ride->exits[peep->current_ride_station].x; - y = ride->exits[peep->current_ride_station].y; - sint16 z = ride->station_heights[peep->current_ride_station]; - - rct_tile_element * tile_element = ride_get_station_exit_element(ride, x, y, z); - - uint8 exit_direction = (tile_element == nullptr ? 0 : tile_element_get_direction(tile_element)); - exit_direction ^= (1 << 1); + auto exit = ride_get_exit_location(peep->current_ride, peep->current_ride_station); + x = exit.x; + y = exit.y; + uint8 exit_direction = exit.direction ^ 2; x *= 32; y *= 32; @@ -3927,13 +3923,8 @@ static void peep_update_ride_sub_state_14(rct_peep * peep) if (last_ride) { - x = ride->exits[peep->current_ride_station].x; - y = ride->exits[peep->current_ride_station].y; - sint16 z = ride->station_heights[peep->current_ride_station]; - - rct_tile_element * tile_element = ride_get_station_exit_element(ride, x, y, z); - - uint8 exit_direction = (tile_element == nullptr ? 0 : tile_element_get_direction(tile_element)); + auto exit = ride_get_exit_location(peep->current_ride, peep->current_ride_station); + uint8 exit_direction = exit.direction; peep->var_37 = (exit_direction * 4) | (peep->var_37 & 0x30) | 1; x = ride->station_starts[peep->current_ride_station].x; @@ -4126,14 +4117,11 @@ static void peep_update_ride_sub_state_16(rct_peep * peep) peep->var_37 |= 3; - x = ride->exits[peep->current_ride_station].x; - y = ride->exits[peep->current_ride_station].y; - sint16 z = ride->station_heights[peep->current_ride_station]; + auto exit = ride_get_exit_location(peep->current_ride, peep->current_ride_station); + x = exit.x; + y = exit.y; - rct_tile_element * tile_element = ride_get_station_exit_element(ride, x, y, z); - - uint8 exit_direction = (tile_element == nullptr ? 0 : tile_element_get_direction(tile_element)); - exit_direction ^= (1 << 1); + uint8 exit_direction = exit.direction ^ 2; x *= 32; y *= 32; @@ -5122,12 +5110,12 @@ static bool peep_update_fixing_sub_state_12(bool firstRun, rct_peep * peep, Ride if (!firstRun) { - LocationXY8 stationPosition = ride->exits[peep->current_ride_station]; - if (stationPosition.xy == RCT_XY8_UNDEFINED) + TileCoordsXYZD stationPosition = ride_get_exit_location(ride, peep->current_ride_station); + if (stationPosition.isNull()) { - stationPosition = ride->entrances[peep->current_ride_station]; + stationPosition = ride_get_entrance_location(ride, peep->current_ride_station); - if (stationPosition.xy == RCT_XY8_UNDEFINED) + if (stationPosition.isNull()) { return true; } @@ -5214,12 +5202,12 @@ static bool peep_update_fixing_sub_state_14(bool firstRun, rct_peep * peep, Ride if (!firstRun) { - LocationXY8 exitPosition = ride->exits[peep->current_ride_station]; - if (exitPosition.xy == RCT_XY8_UNDEFINED) + TileCoordsXYZD exitPosition = ride_get_exit_location(ride, peep->current_ride_station); + if (exitPosition.isNull()) { - exitPosition = ride->entrances[peep->current_ride_station]; + exitPosition = ride_get_entrance_location(ride, peep->current_ride_station); - if (exitPosition.xy == RCT_XY8_UNDEFINED) + if (exitPosition.isNull()) { peep_decrement_num_riders(peep); peep->state = 0; @@ -6504,7 +6492,7 @@ static void peep_update_heading_to_inspect(rct_peep * peep) return; } - if (ride->exits[peep->current_ride_station].xy == RCT_XY8_UNDEFINED) + if (ride_get_exit_location(ride, peep->current_ride_station).isNull()) { ride->lifecycle_flags &= ~RIDE_LIFECYCLE_DUE_INSPECTION; peep_decrement_num_riders(peep); @@ -6565,7 +6553,7 @@ static void peep_update_heading_to_inspect(rct_peep * peep) if (_unk_F1EE18 & F1EE18_RIDE_ENTRANCE) { - if (ride->exits[exit_index].xy != RCT_XY8_UNDEFINED) + if (!ride_get_exit_location(ride, exit_index).isNull()) { return; } @@ -6691,7 +6679,7 @@ static void peep_update_answering(rct_peep * peep) if (_unk_F1EE18 & F1EE18_RIDE_ENTRANCE) { - if (ride->exits[exit_index].xy != RCT_XY8_UNDEFINED) + if (!ride_get_exit_location(ride, exit_index).isNull()) { return; } @@ -11443,15 +11431,17 @@ static sint32 guest_path_finding(rct_peep * peep) for (uint8 stationNum = 0; stationNum < MAX_STATIONS; ++stationNum) { - if (ride->entrances[stationNum].xy == - RCT_XY8_UNDEFINED) // stationNum has no entrance (so presumably an exit only station). + // Skip if stationNum has no entrance (so presumably an exit only station) + if (ride_get_entrance_location(rideIndex, stationNum).isNull()) continue; numEntranceStations++; entranceStations |= (1 << stationNum); - sint16 stationX = (ride->entrances[stationNum]).x * 32; - sint16 stationY = (ride->entrances[stationNum]).y * 32; + TileCoordsXYZD entranceLocation = ride_get_entrance_location(rideIndex, stationNum); + + sint16 stationX = (sint16)(entranceLocation.x * 32); + sint16 stationY = (sint16)(entranceLocation.y * 32); uint16 dist = abs(stationX - peep->next_x) + abs(stationY - peep->next_y); if (dist < closestDist) @@ -11488,15 +11478,21 @@ static sint32 guest_path_finding(rct_peep * peep) closestStationNum = bitscanforward(entranceStations); } - LocationXY8 entranceXY; if (numEntranceStations == 0) - entranceXY = ride->station_starts[closestStationNum]; // closestStationNum is always 0 here. + { + // closestStationNum is always 0 here. + LocationXY8 entranceXY = ride->station_starts[closestStationNum]; + x = entranceXY.x * 32; + y = entranceXY.y * 32; + z = ride->station_heights[closestStationNum]; + } else - entranceXY = ride->entrances[closestStationNum]; - - x = entranceXY.x * 32; - y = entranceXY.y * 32; - z = ride->station_heights[closestStationNum]; + { + TileCoordsXYZD entranceXYZD = ride_get_entrance_location(rideIndex, closestStationNum); + x = entranceXYZD.x * 32; + y = entranceXYZD.y * 32; + z = entranceXYZD.z; + } get_ride_queue_end(&x, &y, &z); diff --git a/src/openrct2/peep/Staff.cpp b/src/openrct2/peep/Staff.cpp index 9c8131f438..2ae4a16afa 100644 --- a/src/openrct2/peep/Staff.cpp +++ b/src/openrct2/peep/Staff.cpp @@ -1209,13 +1209,10 @@ static uint8 staff_mechanic_direction_surface(rct_peep * peep) if ((peep->state == PEEP_STATE_ANSWERING || peep->state == PEEP_STATE_HEADING_TO_INSPECTION) && scenario_rand() & 1) { - - Ride * ride = get_ride(peep->current_ride); - - LocationXY8 location = ride->exits[peep->current_ride_station]; - if (location.xy == RCT_XY8_UNDEFINED) + TileCoordsXYZD location = ride_get_exit_location(peep->current_ride, peep->current_ride_station); + if (location.isNull()) { - location = ride->entrances[peep->current_ride_station]; + location = ride_get_entrance_location(peep->current_ride, peep->current_ride_station); } LocationXY16 chosenTile = { static_cast(location.x * 32), static_cast(location.y * 32) }; @@ -1306,13 +1303,13 @@ static uint8 staff_mechanic_direction_path(rct_peep * peep, uint8 validDirection { /* Find location of the exit for the target ride station * or if the ride has no exit, the entrance. */ - TileCoordsXYZD location = ride_get_exit_location_of_station(peep->current_ride, peep->current_ride_station); - if (location.x == LOCATION_NULL) + TileCoordsXYZD location = ride_get_exit_location(peep->current_ride, peep->current_ride_station); + if (location.isNull()) { - location = ride_get_entrance_location_of_station(peep->current_ride, peep->current_ride_station); + location = ride_get_entrance_location(peep->current_ride, peep->current_ride_station); // If no entrance is present either. This is an incorrect state. - if (location.x == LOCATION_NULL) + if (location.isNull()) { return staff_mechanic_direction_path_rand(peep, pathDirections); } diff --git a/src/openrct2/rct1/S4Importer.cpp b/src/openrct2/rct1/S4Importer.cpp index 898de56576..688cab05d0 100644 --- a/src/openrct2/rct1/S4Importer.cpp +++ b/src/openrct2/rct1/S4Importer.cpp @@ -234,6 +234,7 @@ public: ImportSavedView(); FixLandOwnership(); CountBlockSections(); + determine_ride_entrance_and_exit_locations(); // Importing the strings is done later on, although that approach needs looking at. //game_convert_strings_to_utf8(); @@ -792,8 +793,17 @@ private: dst->train_at_station[i] = src->station_depart[i]; - dst->entrances[i] = src->entrance[i]; - dst->exits[i] = src->exit[i]; + // Direction is fixed later. + if (src->entrance[i].xy == RCT_XY8_UNDEFINED) + ride_clear_entrance_location(dst, i); + else + ride_set_entrance_location(dst, i, { src->entrance[i].x, src->entrance[i].y, src->station_height[i] / 2, 0}); + + if (src->exit[i].xy == RCT_XY8_UNDEFINED) + ride_clear_exit_location(dst, i); + else + ride_set_exit_location(dst, i, { src->exit[i].x, src->exit[i].y, src->station_height[i] / 2, 0}); + dst->queue_time[i] = src->queue_time[i]; dst->last_peep_in_queue[i] = src->last_peep_in_queue[i]; dst->queue_length[i] = src->num_peeps_in_queue[i]; @@ -806,8 +816,8 @@ private: { dst->station_starts[i].xy = RCT_XY8_UNDEFINED; dst->train_at_station[i] = 255; - dst->entrances[i].xy = RCT_XY8_UNDEFINED; - dst->exits[i].xy = RCT_XY8_UNDEFINED; + ride_clear_entrance_location(dst, i); + ride_clear_exit_location(dst, i); dst->last_peep_in_queue[i] = SPRITE_INDEX_NULL; } diff --git a/src/openrct2/rct2/S6Exporter.cpp b/src/openrct2/rct2/S6Exporter.cpp index 9d154bac92..6f8cede678 100644 --- a/src/openrct2/rct2/S6Exporter.cpp +++ b/src/openrct2/rct2/S6Exporter.cpp @@ -52,6 +52,7 @@ #include "../world/MapAnimation.h" #include "../world/Park.h" #include "../world/Sprite.h" +#include "../ride/Station.h" S6Exporter::S6Exporter() { @@ -485,8 +486,19 @@ void S6Exporter::ExportRide(rct2_ride * dst, const Ride * src) dst->station_length[i] = src->station_length[i]; dst->station_depart[i] = src->station_depart[i]; dst->train_at_station[i] = src->train_at_station[i]; - dst->entrances[i] = src->entrances[i]; - dst->exits[i] = src->exits[i]; + + TileCoordsXYZD entrance = ride_get_entrance_location(src, i); + if (entrance.isNull()) + dst->entrances[i].xy = RCT_XY8_UNDEFINED; + else + dst->entrances[i] = { (uint8)entrance.x, (uint8)entrance.y }; + + TileCoordsXYZD exit = ride_get_exit_location(src, i); + if (exit.isNull()) + dst->exits[i].xy = RCT_XY8_UNDEFINED; + else + dst->exits[i] = { (uint8)exit.x, (uint8)exit.y }; + dst->last_peep_in_queue[i] = src->last_peep_in_queue[i]; dst->length[i] = src->length[i]; diff --git a/src/openrct2/rct2/S6Importer.cpp b/src/openrct2/rct2/S6Importer.cpp index b05eb51c27..430f608b0f 100644 --- a/src/openrct2/rct2/S6Importer.cpp +++ b/src/openrct2/rct2/S6Importer.cpp @@ -447,6 +447,7 @@ public: map_update_tile_pointers(); game_convert_strings_to_utf8(); map_count_remaining_land_rights(); + determine_ride_entrance_and_exit_locations(); // We try to fix the cycles on import, hence the 'true' parameter check_for_sprite_list_cycles(true); @@ -517,8 +518,18 @@ public: dst->station_length[i] = src->station_length[i]; dst->station_depart[i] = src->station_depart[i]; dst->train_at_station[i] = src->train_at_station[i]; - dst->entrances[i] = src->entrances[i]; - dst->exits[i] = src->exits[i]; + // Direction is fixed later. + + if (src->entrances[i].xy == RCT_XY8_UNDEFINED) + ride_clear_entrance_location(dst, i); + else + ride_set_entrance_location(dst, i, { src->entrances[i].x, src->entrances[i].y, src->station_heights[i], 0 }); + + if (src->exits[i].xy == RCT_XY8_UNDEFINED) + ride_clear_exit_location(dst, i); + else + ride_set_exit_location(dst, i, { src->entrances[i].x, src->entrances[i].y, src->station_heights[i], 0 }); + dst->last_peep_in_queue[i] = src->last_peep_in_queue[i]; dst->length[i] = src->length[i]; @@ -533,8 +544,8 @@ public: { dst->station_starts[i].xy = RCT_XY8_UNDEFINED; dst->train_at_station[i] = 255; - dst->entrances[i].xy = RCT_XY8_UNDEFINED; - dst->exits[i].xy = RCT_XY8_UNDEFINED; + ride_clear_entrance_location(dst, i); + ride_clear_exit_location(dst, i); dst->last_peep_in_queue[i] = SPRITE_INDEX_NULL; } diff --git a/src/openrct2/ride/Ride.cpp b/src/openrct2/ride/Ride.cpp index 70750d8814..3006581258 100644 --- a/src/openrct2/ride/Ride.cpp +++ b/src/openrct2/ride/Ride.cpp @@ -343,7 +343,7 @@ sint32 ride_get_total_queue_length(Ride *ride) { sint32 i, queueLength = 0; for (i = 0; i < MAX_STATIONS; i++) - if (ride->entrances[i].xy != RCT_XY8_UNDEFINED) + if (!ride_get_entrance_location(ride, i).isNull()) queueLength += ride->queue_length[i]; return queueLength; } @@ -352,7 +352,7 @@ sint32 ride_get_max_queue_time(Ride *ride) { uint8 i, queueTime = 0; for (i = 0; i < MAX_STATIONS; i++) - if (ride->entrances[i].xy != RCT_XY8_UNDEFINED) + if (!ride_get_entrance_location(ride, i).isNull()) queueTime = Math::Max(queueTime, ride->queue_time[i]); return (sint32)queueTime; } @@ -1136,14 +1136,13 @@ void ride_remove_peeps(sint32 rideIndex) sint32 exitZ = 0; sint32 exitDirection = 255; if (stationIndex != -1) { - LocationXY8 location = ride->exits[stationIndex]; - if (location.xy != RCT_XY8_UNDEFINED) { + TileCoordsXYZD location = ride_get_exit_location(ride, stationIndex); + if (!location.isNull()) { exitX = location.x; exitY = location.y; - exitZ = ride->station_heights[stationIndex]; - rct_tile_element *tileElement = ride_get_station_exit_element(ride, exitX, exitY, exitZ); + exitZ = location.z; + exitDirection = location.direction; - exitDirection = (tileElement == nullptr ? 0 : tile_element_get_direction(tileElement)); exitX = (exitX * 32) - (word_981D6C[exitDirection].x * 20) + 16; exitY = (exitY * 32) - (word_981D6C[exitDirection].y * 20) + 16; exitZ = (exitZ * 8) + 2; @@ -2662,22 +2661,22 @@ static void ride_call_closest_mechanic(sint32 rideIndex) rct_peep *ride_find_closest_mechanic(Ride *ride, sint32 forInspection) { sint32 x, y, z, stationIndex; - LocationXY8 location; + TileCoordsXYZD location; rct_tile_element *tileElement; // Get either exit position or entrance position if there is no exit stationIndex = ride->inspection_station; - location = ride->exits[stationIndex]; - if (location.xy == RCT_XY8_UNDEFINED) { - location = ride->entrances[stationIndex]; - if (location.xy == RCT_XY8_UNDEFINED) + location = ride_get_exit_location(ride, stationIndex); + if (location.isNull()) { + location = ride_get_entrance_location(ride, stationIndex); + if (location.isNull()) return nullptr; } // Get station start track element and position x = location.x; y = location.y; - z = ride->station_heights[stationIndex]; + z = location.z; tileElement = ride_get_station_exit_element(ride, x, y, z); if (tileElement == nullptr) return nullptr; @@ -3189,26 +3188,17 @@ void ride_check_all_reachable() * rct2: 0x006B7C59 * @return 1 if the coordinate is reachable or has no entrance, 0 otherwise */ -static sint32 ride_entrance_exit_is_reachable(LocationXY8 coordinates, Ride* ride, sint32 index) +static sint32 ride_entrance_exit_is_reachable(TileCoordsXYZD coordinates) { sint32 x, y, z; - rct_tile_element *tileElement; + + if (coordinates.isNull()) + return 1; x = coordinates.x; y = coordinates.y; - z = ride->station_heights[index]; - tileElement = map_get_first_element_at(x, y); - - for (;;) { - if (tile_element_get_type(tileElement) == TILE_ELEMENT_TYPE_ENTRANCE && z == tileElement->base_height) { - break; - } else if (tile_element_is_last_for_tile(tileElement)) { - return 1; - } - tileElement++; - } - - uint8 face_direction = tile_element_get_direction(tileElement); + z = coordinates.z; + uint8 face_direction = coordinates.direction; x *= 32; y *= 32; @@ -3222,14 +3212,16 @@ static sint32 ride_entrance_exit_is_reachable(LocationXY8 coordinates, Ride* rid static void ride_entrance_exit_connected(Ride* ride, sint32 ride_idx) { - for (sint32 i = 0; i < MAX_STATIONS; ++i) { - LocationXY8 station_start = ride->station_starts[i], - entrance = ride->entrances[i], - exit = ride->exits[i]; + for (sint32 i = 0; i < MAX_STATIONS; ++i) + { + LocationXY8 station_start = ride->station_starts[i]; + TileCoordsXYZD entrance = ride_get_entrance_location(ride_idx, i); + TileCoordsXYZD exit = ride_get_exit_location(ride_idx, i); if (station_start.xy == RCT_XY8_UNDEFINED ) continue; - if (entrance.xy != RCT_XY8_UNDEFINED && !ride_entrance_exit_is_reachable(entrance, ride, i)) { + if (!entrance.isNull() && !ride_entrance_exit_is_reachable(entrance)) + { // name of ride is parameter of the format string set_format_arg(0, rct_string_id, ride->name); set_format_arg(2, uint32, ride->name_arguments); @@ -3239,7 +3231,8 @@ static void ride_entrance_exit_connected(Ride* ride, sint32 ride_idx) ride->connected_message_throttle = 3; } - if (exit.xy != RCT_XY8_UNDEFINED && !ride_entrance_exit_is_reachable(exit, ride, i)) { + if (!exit.isNull() && !ride_entrance_exit_is_reachable(exit)) + { // name of ride is parameter of the format string set_format_arg(0, rct_string_id, ride->name); set_format_arg(2, uint32, ride->name_arguments); @@ -3389,7 +3382,7 @@ static void ride_entrance_set_map_tooltip(rct_tile_element *tileElement) if (tileElement->properties.entrance.type == ENTRANCE_TYPE_RIDE_ENTRANCE) { // Get the queue length sint32 queueLength = 0; - if (ride->entrances[stationIndex].xy != RCT_XY8_UNDEFINED) + if (!ride_get_entrance_location(ride, stationIndex).isNull()) queueLength = ride->queue_length[stationIndex]; set_map_tooltip_format_arg(0, rct_string_id, STR_RIDE_MAP_TIP); @@ -4057,17 +4050,19 @@ static sint32 ride_check_for_entrance_exit(sint32 rideIndex) if (ride->station_starts[i].xy == RCT_XY8_UNDEFINED) continue; - if (ride->entrances[i].xy != RCT_XY8_UNDEFINED) { + if (!ride_get_entrance_location(ride, i).isNull()) { entrance = 1; } - if (ride->exits[i].xy != RCT_XY8_UNDEFINED) { + if (!ride_get_exit_location(ride, i).isNull()) { exit = 1; } // If station start and no entrance/exit // Sets same error message as no entrance - if (ride->exits[i].xy == RCT_XY8_UNDEFINED && ride->entrances[i].xy == RCT_XY8_UNDEFINED){ + if (ride_get_exit_location(ride, i).isNull() && + ride_get_entrance_location(ride, i).isNull()) + { entrance = 0; break; } @@ -4092,18 +4087,19 @@ static sint32 ride_check_for_entrance_exit(sint32 rideIndex) */ static void sub_6B5952(sint32 rideIndex) { - Ride *ride = get_ride(rideIndex); - - for (sint32 i = 0; i < MAX_STATIONS; i++) { - LocationXY8 location = ride->entrances[i]; - if (location.xy == RCT_XY8_UNDEFINED) + for (sint32 i = 0; i < MAX_STATIONS; i++) + { + TileCoordsXYZD location = ride_get_entrance_location(rideIndex, i); + if (location.isNull()) continue; sint32 x = location.x * 32; sint32 y = location.y * 32; - sint32 z = ride->station_heights[i]; + sint32 z = location.z; - rct_tile_element *tileElement = map_get_first_element_at(x / 32, y / 32); + // This will fire for every entrance on this x, y and z, regardless whether that actually belongs to + // the ride or not. + rct_tile_element * tileElement = map_get_first_element_at(location.x, location.y); do { if (tile_element_get_type(tileElement) != TILE_ELEMENT_TYPE_ENTRANCE) continue; @@ -4385,27 +4381,32 @@ static void ride_set_boat_hire_return_point(Ride * ride, CoordsXYE * startElemen static void ride_set_maze_entrance_exit_points(Ride *ride) { // Needs room for an entrance and an exit per station, plus one position for the list terminator. - uint16 positions[(MAX_STATIONS * 2) + 1]; + TileCoordsXYZD positions[(MAX_STATIONS * 2) + 1]; // Create a list of all the entrance and exit positions - uint16 *position = positions; - for (sint32 i = 0; i < MAX_STATIONS; i++) { - if (ride->entrances[i].xy != RCT_XY8_UNDEFINED) { - *position++ = ride->entrances[i].xy; + TileCoordsXYZD * position = positions; + for (sint32 i = 0; i < MAX_STATIONS; i++) + { + const auto entrance = ride_get_entrance_location(ride, i); + const auto exit = ride_get_exit_location(ride, i); + + if (!entrance.isNull()) { + *position++ = entrance; } - if (ride->exits[i].xy != RCT_XY8_UNDEFINED) { - *position++ = ride->exits[i].xy; + if (!exit.isNull()) { + *position++ = exit; } } - *position++ = RCT_XY8_UNDEFINED; + (*position++).x = COORDS_NULL; // Enumerate entrance and exit positions - for (position = positions; *position != RCT_XY8_UNDEFINED; position++) { - sint32 x = (*position & 0xFF) << 5; - sint32 y = (*position >> 8) << 5; - sint32 z = ride->station_heights[0]; + for (position = positions; !(*position).isNull(); position++) + { + sint32 x = (*position).x << 5; + sint32 y = (*position).y << 5; + sint32 z = (*position).z; - rct_tile_element *tileElement = map_get_first_element_at(x >> 5, y >> 5); + rct_tile_element *tileElement = map_get_first_element_at((*position).x, (*position).y); do { if (tile_element_get_type(tileElement) != TILE_ELEMENT_TYPE_ENTRANCE) continue; if ( @@ -5139,12 +5140,12 @@ static void loc_6B51C0(sint32 rideIndex) if (ride->station_starts[i].xy == RCT_XY8_UNDEFINED) continue; - if (ride->entrances[i].xy == RCT_XY8_UNDEFINED) { + if (ride_get_entrance_location(rideIndex, i).isNull()) { entranceOrExit = 0; break; } - if (ride->exits[i].xy == RCT_XY8_UNDEFINED) { + if (ride_get_exit_location(rideIndex, i).isNull()) { entranceOrExit = 1; break; } @@ -6834,11 +6835,12 @@ bool ride_are_all_possible_entrances_and_exits_built(Ride *ride) { continue; } - if (ride->entrances[i].xy == RCT_XY8_UNDEFINED) { + if (ride_get_entrance_location(ride, i).isNull()) + { gGameCommandErrorText = STR_ENTRANCE_NOT_YET_BUILT; return false; } - if (ride->exits[i].xy == RCT_XY8_UNDEFINED) { + if (ride_get_exit_location(ride, i).isNull()) { gGameCommandErrorText = STR_EXIT_NOT_YET_BUILT; return false; } @@ -7517,42 +7519,47 @@ void sub_6CB945(sint32 rideIndex) } // Needs room for an entrance and an exit per station, plus one position for the list terminator. - uint16 locations[(MAX_STATIONS * 2) + 1]; - uint16 *locationList = locations; - for (uint8 stationId = 0; stationId < MAX_STATIONS; ++stationId) { - if (ride->entrances[stationId].xy != RCT_XY8_UNDEFINED) { - *locationList++ = ride->entrances[stationId].xy; - ride->entrances[stationId].xy = RCT_XY8_UNDEFINED; + TileCoordsXYZD locations[(MAX_STATIONS * 2) + 1]; + TileCoordsXYZD *locationList = locations; + for (uint8 stationId = 0; stationId < MAX_STATIONS; ++stationId) + { + TileCoordsXYZD entrance = ride_get_entrance_location(rideIndex, stationId); + if (!entrance.isNull()) + { + *locationList++ = entrance; + ride_clear_entrance_location(ride, stationId); } - if (ride->exits[stationId].xy != RCT_XY8_UNDEFINED) { - *locationList++ = ride->exits[stationId].xy; - ride->exits[stationId].xy = RCT_XY8_UNDEFINED; + TileCoordsXYZD exit = ride_get_exit_location(rideIndex, stationId); + if (!exit.isNull()) + { + *locationList++ = exit; + ride_clear_exit_location(ride, stationId); } } - *locationList++ = RCT_XY8_UNDEFINED; + (*locationList++).x = COORDS_NULL; locationList = locations; - for (; *locationList != RCT_XY8_UNDEFINED; locationList++) { - uint16* locationList2 = locationList; + for (; !(*locationList).isNull(); locationList++) { + TileCoordsXYZD * locationList2 = locationList; locationList2++; bool duplicateLocation = false; do { - if (*locationList == *locationList2) { + if ((*locationList).x == (*locationList2).x && + (*locationList).y == (*locationList2).y) + { duplicateLocation = true; break; } - } while (*locationList2++ != RCT_XY8_UNDEFINED); + } while (!(*locationList2++).isNull()); - if (duplicateLocation == true) { + if (duplicateLocation) + { continue; } - LocationXY16 location = { - (sint16)((*locationList & 0xFF) * 32), - (sint16)(((*locationList >> 8) & 0xFF) * 32) - }; + CoordsXY location = { (*locationList).x * 32, (*locationList).y * 32 }; rct_tile_element *tileElement = map_get_first_element_at(location.x >> 5, location.y >> 5); do { @@ -7560,7 +7567,7 @@ void sub_6CB945(sint32 rideIndex) if (tileElement->properties.entrance.ride_index != rideIndex) continue; if (tileElement->properties.entrance.type > ENTRANCE_TYPE_RIDE_EXIT) continue; - LocationXY16 nextLocation = location; + CoordsXY nextLocation = location; nextLocation.x += TileDirectionDelta[tile_element_get_direction(tileElement)].x; nextLocation.y += TileDirectionDelta[tile_element_get_direction(tileElement)].y; @@ -7585,18 +7592,21 @@ void sub_6CB945(sint32 rideIndex) stationId = tile_element_get_station(trackElement); } - if (tileElement->properties.entrance.type == ENTRANCE_TYPE_RIDE_EXIT) { - if (ride->exits[stationId].xy != RCT_XY8_UNDEFINED) { + if (tileElement->properties.entrance.type == ENTRANCE_TYPE_RIDE_EXIT) + { + if (!ride_get_exit_location(ride, stationId).isNull()) break; - } - ride->exits[stationId].x = location.x / 32; - ride->exits[stationId].y = location.y / 32; - } else { - if (ride->entrances[stationId].xy != RCT_XY8_UNDEFINED) { + + ride_set_exit_location(ride, stationId, + { location.x / 32, location.y / 32, ride->station_heights[stationId], (uint8)tile_element_get_direction(tileElement) }); + } + else + { + if (!ride_get_entrance_location(ride, stationId).isNull()) break; - } - ride->entrances[stationId].x = location.x / 32; - ride->entrances[stationId].y = location.y / 32; + + ride_set_entrance_location(ride, stationId, + { location.x / 32, location.y / 32, ride->station_heights[stationId], (uint8)tile_element_get_direction(tileElement) }); } tileElement->properties.entrance.index &= 0x8F; @@ -8243,7 +8253,13 @@ LocationXY16 ride_get_rotated_coords(sint16 x, sint16 y, sint16 z) return rotatedCoords; } -void fix_ride_entrance_and_exit_locations() +// Normally, a station has at most one entrance and one exit, which are at the same height +// as the station. But in hacked parks, neither can be taken for granted. This code ensures +// that the ride->entrances and ride->exits arrays will point to one of them. There is +// an ever-so-slight chance two entrances/exits for the same station reside on the same tile. +// In cases like this, the one at station height will be considered the "true" one. +// If none exists at that height, newer and higher placed ones take precedence. +void determine_ride_entrance_and_exit_locations() { sint32 rideIndex; Ride * ride; @@ -8252,32 +8268,39 @@ void fix_ride_entrance_and_exit_locations() { for (sint32 stationIndex = 0; stationIndex < MAX_STATIONS; stationIndex++) { - const LocationXY8 entranceLoc = ride->entrances[stationIndex]; - const LocationXY8 exitLoc = ride->exits[stationIndex]; - uint8 entranceExitHeight = ride->station_heights[stationIndex]; + TileCoordsXYZD entranceLoc = ride->entrances[stationIndex]; + TileCoordsXYZD exitLoc = ride->exits[stationIndex]; bool fixEntrance = false; bool fixExit = false; const rct_tile_element * tileElement; // Skip if the station has no entrance - if (entranceLoc.xy != RCT_XY8_UNDEFINED) + if (!entranceLoc.isNull()) { - tileElement = map_get_ride_entrance_element_at(entranceLoc.x * 32, entranceLoc.y * 32, entranceExitHeight, false); + tileElement = map_get_ride_entrance_element_at(entranceLoc.x * 32, entranceLoc.y * 32, entranceLoc.z, false); if (tileElement == nullptr || tileElement->properties.entrance.ride_index != rideIndex || tile_element_get_station(tileElement) != stationIndex) { fixEntrance = true; } + else + { + ride->entrances[stationIndex].direction = (uint8)tile_element_get_direction(tileElement); + } } - if (exitLoc.xy != RCT_XY8_UNDEFINED) + if (!exitLoc.isNull()) { - tileElement = map_get_ride_exit_element_at(exitLoc.x * 32, exitLoc.y * 32, entranceExitHeight, false); + tileElement = map_get_ride_exit_element_at(exitLoc.x * 32, exitLoc.y * 32, entranceLoc.z, false); if (tileElement == nullptr || tileElement->properties.entrance.ride_index != rideIndex || tile_element_get_station(tileElement) != stationIndex) { fixExit = true; } + else + { + ride->exits[stationIndex].direction = (uint8)tile_element_get_direction(tileElement); + } } if (!fixEntrance && !fixExit) @@ -8312,36 +8335,37 @@ void fix_ride_entrance_and_exit_locations() continue; } + // The expected height is where entrances and exit reside in non-hacked parks. + const uint8 expectedHeight = ride->station_heights[stationIndex]; + if (fixEntrance && tileElement->properties.entrance.type == ENTRANCE_TYPE_RIDE_ENTRANCE) { - // There are some cases (like Belmont Shores), where there is both a sunk and a disconnected entrance. - // Not sure why, but in this case, pick the highest one. - if (alreadyFoundEntrance && ride->station_heights[stationIndex] > tileElement->base_height) + if (alreadyFoundEntrance) { - continue; + if (ride->entrances[stationIndex].z == expectedHeight) + continue; + if (ride->entrances[stationIndex].z > tileElement->base_height) + continue; } // Found our entrance - ride->entrances[stationIndex].x = x; - ride->entrances[stationIndex].y = y; - ride->station_heights[stationIndex] = tileElement->base_height; - + ride_set_entrance_location(ride, stationIndex, { x, y, tileElement->base_height, (uint8)tile_element_get_direction(tileElement) }); alreadyFoundEntrance = true; log_info("Fixed disconnected entrance of ride %d, station %d to x = %d, y = %d and z = %d.", rideIndex, stationIndex, x, y, tileElement->base_height); } else if (fixExit && tileElement->properties.entrance.type == ENTRANCE_TYPE_RIDE_EXIT) { - if (alreadyFoundExit && ride->station_heights[stationIndex] > tileElement->base_height) + if (alreadyFoundExit) { - continue; + if (ride->exits[stationIndex].z == expectedHeight) + continue; + if (ride->exits[stationIndex].z > tileElement->base_height) + continue; } // Found our exit - ride->exits[stationIndex].x = x; - ride->exits[stationIndex].y = y; - ride->station_heights[stationIndex] = tileElement->base_height; - + ride_set_exit_location(ride, stationIndex, { x, y, tileElement->base_height, (uint8)tile_element_get_direction(tileElement) }); alreadyFoundExit = true; log_info("Fixed disconnected exit of ride %d, station %d to x = %d, y = %d and z = %d.", rideIndex, stationIndex, x, y, tileElement->base_height); @@ -8354,13 +8378,13 @@ void fix_ride_entrance_and_exit_locations() if (fixEntrance && !alreadyFoundEntrance) { - ride->entrances[stationIndex].xy = RCT_XY8_UNDEFINED; + ride_clear_entrance_location(ride, stationIndex); log_info("Cleared disconnected entrance of ride %d, station %d.", rideIndex, stationIndex); } if (fixExit && !alreadyFoundExit) { - ride->exits[stationIndex].xy = RCT_XY8_UNDEFINED; + ride_clear_exit_location(ride, stationIndex); log_info("Cleared disconnected exit of ride %d, station %d.", rideIndex, stationIndex); } } diff --git a/src/openrct2/ride/Ride.h b/src/openrct2/ride/Ride.h index d2c9969a33..8b07a04109 100644 --- a/src/openrct2/ride/Ride.h +++ b/src/openrct2/ride/Ride.h @@ -163,8 +163,8 @@ struct Ride // ride->vehicle index for current train waiting for passengers // at station uint8 train_at_station[MAX_STATIONS]; - LocationXY8 entrances[MAX_STATIONS]; - LocationXY8 exits[MAX_STATIONS]; + TileCoordsXYZD entrances[MAX_STATIONS]; + TileCoordsXYZD exits[MAX_STATIONS]; uint16 last_peep_in_queue[MAX_STATIONS]; uint16 vehicles[MAX_VEHICLES_PER_RIDE]; // Points to the first car in the train uint8 depart_flags; @@ -1194,6 +1194,6 @@ void ride_stop_peeps_queuing(sint32 rideIndex); LocationXY16 ride_get_rotated_coords(sint16 x, sint16 y, sint16 z); -void fix_ride_entrance_and_exit_locations(); +void determine_ride_entrance_and_exit_locations(); #endif diff --git a/src/openrct2/ride/RideRatings.cpp b/src/openrct2/ride/RideRatings.cpp index 09fc7ecc68..78507711e8 100644 --- a/src/openrct2/ride/RideRatings.cpp +++ b/src/openrct2/ride/RideRatings.cpp @@ -186,7 +186,8 @@ static void ride_ratings_update_state_1() */ static void ride_ratings_update_state_2() { - Ride *ride = get_ride(gRideRatingsCalcData.current_ride); + const sint32 rideIndex = gRideRatingsCalcData.current_ride; + Ride *ride = get_ride(rideIndex); if (ride->type == RIDE_TYPE_NULL || ride->status == RIDE_STATUS_CLOSED) { gRideRatingsCalcData.state = RIDE_RATINGS_STATE_FIND_NEXT_RIDE; return; @@ -211,7 +212,8 @@ static void ride_ratings_update_state_2() if (trackType == TRACK_ELEM_END_STATION) { sint32 entranceIndex = tile_element_get_station(tileElement); gRideRatingsCalcData.station_flags &= ~RIDE_RATING_STATION_FLAG_NO_ENTRANCE; - if (ride->entrances[entranceIndex].xy == RCT_XY8_UNDEFINED) { + if (ride_get_entrance_location(rideIndex, entranceIndex).isNull()) + { gRideRatingsCalcData.station_flags |= RIDE_RATING_STATION_FLAG_NO_ENTRANCE; } } @@ -336,7 +338,8 @@ static void ride_ratings_update_state_5() */ static void ride_ratings_begin_proximity_loop() { - Ride *ride = get_ride(gRideRatingsCalcData.current_ride); + const sint32 rideIndex = gRideRatingsCalcData.current_ride; + Ride *ride = get_ride(rideIndex); if (ride->type == RIDE_TYPE_NULL || ride->status == RIDE_STATUS_CLOSED) { gRideRatingsCalcData.state = RIDE_RATINGS_STATE_FIND_NEXT_RIDE; return; @@ -350,7 +353,8 @@ static void ride_ratings_begin_proximity_loop() for (sint32 i = 0; i < MAX_STATIONS; i++) { if (ride->station_starts[i].xy != RCT_XY8_UNDEFINED) { gRideRatingsCalcData.station_flags &= ~RIDE_RATING_STATION_FLAG_NO_ENTRANCE; - if (ride->entrances[i].xy == RCT_XY8_UNDEFINED) { + if (ride_get_entrance_location(rideIndex, i).isNull()) + { gRideRatingsCalcData.station_flags |= RIDE_RATING_STATION_FLAG_NO_ENTRANCE; } @@ -1264,7 +1268,7 @@ static rating_tuple ride_ratings_get_drop_ratings(Ride *ride) static sint32 ride_ratings_get_scenery_score(Ride *ride) { sint8 i = ride_get_first_valid_station_start(ride); - LocationXY8 location; + sint32 x, y; if (i == -1) { @@ -1273,15 +1277,17 @@ static sint32 ride_ratings_get_scenery_score(Ride *ride) if (ride->type == RIDE_TYPE_MAZE) { - location = ride->entrances[0]; + TileCoordsXYZD location = ride_get_entrance_location(ride, 0); + x = location.x; + y = location.y; } else { - location = ride->station_starts[i]; + LocationXY8 location = ride->station_starts[i]; + x = location.x; + y = location.y; } - sint32 x = location.x; - sint32 y = location.y; sint32 z = tile_element_height(x * 32, y * 32) & 0xFFFF; // Check if station is underground, returns a fixed mediocre score since you can't have scenery underground diff --git a/src/openrct2/ride/Station.cpp b/src/openrct2/ride/Station.cpp index 5913405144..b23a874499 100644 --- a/src/openrct2/ride/Station.cpp +++ b/src/openrct2/ride/Station.cpp @@ -346,7 +346,7 @@ sint8 ride_get_first_valid_station_exit(Ride * ride) { for (sint32 i = 0; i < MAX_STATIONS; i++) { - if (ride->exits[i].xy != RCT_XY8_UNDEFINED) + if (ride->exits[i].x != COORDS_NULL) { return i; } @@ -378,62 +378,48 @@ sint8 ride_get_first_empty_station_start(const Ride * ride) return -1; } -static TileCoordsXYZD ride_get_entrance_or_exit_location_of_station( - const uint8 rideIndex, - const uint8 stationIndex, - const uint8 entranceType) +TileCoordsXYZD ride_get_entrance_location(const sint32 rideIndex, const sint32 stationIndex) { const Ride * ride = get_ride(rideIndex); - LocationXY8 tileLocation = {}; - - if (entranceType == ENTRANCE_TYPE_RIDE_ENTRANCE) - { - tileLocation = ride->entrances[stationIndex]; - } - else - { - tileLocation = ride->exits[stationIndex]; - } - - // Normally, a station has at most one entrance and one exit, which are at the same height - // as the station. But in hacked parks, neither can be taken for granted. Import code ensures - // that the ride->entrances and ride->exits arrays will point to one of them. There is, however, - // an ever-so-slight chance two entrances/exits for the same station reside on the same tile. - // In cases like this, the one at station height will be considered the "true" one. - // If none exists at that height, newer ones take precedence. - rct_tile_element * tileElement = map_get_first_element_at(tileLocation.x, tileLocation.y); - TileCoordsXYZD retVal = { LOCATION_NULL, LOCATION_NULL, LOCATION_NULL, 0 }; - const uint8 expectedHeight = ride->station_heights[stationIndex]; - - if (tileElement != nullptr && tileLocation.xy != RCT_XY8_UNDEFINED) - { - do - { - if (tile_element_get_type(tileElement) != TILE_ELEMENT_TYPE_ENTRANCE) - continue; - if (entrance_element_get_type(tileElement) != entranceType) - continue; - if (tile_element_get_ride_index(tileElement) != rideIndex) - continue; - if (tile_element_get_station(tileElement) != stationIndex) - continue; - - retVal = { tileLocation.x, tileLocation.y, tileElement->base_height, (uint8)tile_element_get_direction(tileElement) }; - if (tileElement->base_height == expectedHeight) - break; - } - while (!tile_element_is_last_for_tile(tileElement++)); - } - - return retVal; + return ride->entrances[stationIndex]; } -TileCoordsXYZD ride_get_entrance_location_of_station(const uint8 rideIndex, const uint8 stationIndex) +TileCoordsXYZD ride_get_exit_location(const sint32 rideIndex, const sint32 stationIndex) { - return ride_get_entrance_or_exit_location_of_station(rideIndex, stationIndex, ENTRANCE_TYPE_RIDE_ENTRANCE); + const Ride * ride = get_ride(rideIndex); + return ride->exits[stationIndex]; } -TileCoordsXYZD ride_get_exit_location_of_station(const uint8 rideIndex, const uint8 stationIndex) +TileCoordsXYZD ride_get_entrance_location(const Ride * ride, const sint32 stationIndex) { - return ride_get_entrance_or_exit_location_of_station(rideIndex, stationIndex, ENTRANCE_TYPE_RIDE_EXIT); -} \ No newline at end of file + return ride->entrances[stationIndex]; +} + +TileCoordsXYZD ride_get_exit_location(const Ride * ride, const sint32 stationIndex) +{ + return ride->exits[stationIndex]; +} + +void ride_clear_entrance_location( + Ride * ride, + const sint32 stationIndex) +{ + ride->entrances[stationIndex].x = COORDS_NULL; +} + +void ride_clear_exit_location( + Ride * ride, + const sint32 stationIndex) +{ + ride->exits[stationIndex].x = COORDS_NULL; +} + +void ride_set_entrance_location(Ride * ride, const sint32 stationIndex, const TileCoordsXYZD location) +{ + ride->entrances[stationIndex] = location; +} + +void ride_set_exit_location(Ride * ride, const sint32 stationIndex, const TileCoordsXYZD location) +{ + ride->exits[stationIndex] = location; +} diff --git a/src/openrct2/ride/Station.h b/src/openrct2/ride/Station.h index 69f5559292..6a6240300c 100644 --- a/src/openrct2/ride/Station.h +++ b/src/openrct2/ride/Station.h @@ -25,6 +25,13 @@ sint8 ride_get_first_valid_station_exit(Ride * ride); sint8 ride_get_first_valid_station_start(const Ride * ride); sint8 ride_get_first_empty_station_start(const Ride * ride); -TileCoordsXYZD ride_get_entrance_location_of_station(const uint8 rideIndex, const uint8 stationIndex); -TileCoordsXYZD ride_get_exit_location_of_station(const uint8 rideIndex, const uint8 stationIndex); +TileCoordsXYZD ride_get_entrance_location(const sint32 rideIndex, const sint32 stationIndex); +TileCoordsXYZD ride_get_exit_location(const sint32 rideIndex, const sint32 stationIndex); +TileCoordsXYZD ride_get_entrance_location(const Ride * ride, const sint32 stationIndex); +TileCoordsXYZD ride_get_exit_location(const Ride * ride, const sint32 stationIndex); +void ride_clear_entrance_location(Ride * ride, const sint32 stationIndex); +void ride_clear_exit_location(Ride * ride, const sint32 stationIndex); + +void ride_set_entrance_location(Ride * ride, const sint32 stationIndex, const TileCoordsXYZD location); +void ride_set_exit_location(Ride * ride, const sint32 stationIndex, const TileCoordsXYZD location); \ No newline at end of file diff --git a/src/openrct2/ride/TrackDesignSave.cpp b/src/openrct2/ride/TrackDesignSave.cpp index 6df3b7f2fe..74dc47fcac 100644 --- a/src/openrct2/ride/TrackDesignSave.cpp +++ b/src/openrct2/ride/TrackDesignSave.cpp @@ -36,6 +36,7 @@ #include "TrackData.h" #include "TrackDesign.h" #include "TrackDesignRepository.h" +#include "Station.h" #define TRACK_MAX_SAVED_TILE_ELEMENTS 1500 @@ -860,10 +861,10 @@ static bool track_design_save_to_td6_for_maze(uint8 rideIndex, rct_track_td6 *td x = 0; } - Ride *ride = get_ride(rideIndex); - LocationXY8 location = ride->entrances[0]; + TileCoordsXYZD location = ride_get_entrance_location(rideIndex, 0); - if (location.xy == RCT_XY8_UNDEFINED) { + if (location.isNull()) + { gGameCommandErrorText = STR_TRACK_TOO_LARGE_OR_TOO_MUCH_SCENERY; SafeFree(td6->maze_elements); return false; @@ -888,11 +889,12 @@ static bool track_design_save_to_td6_for_maze(uint8 rideIndex, rct_track_td6 *td maze++; numMazeElements++; - location = ride->exits[0]; - if (location.xy == RCT_XY8_UNDEFINED) { + location = ride_get_entrance_location(rideIndex, 0); + if (location.isNull()) + { gGameCommandErrorText = STR_TRACK_TOO_LARGE_OR_TOO_MUCH_SCENERY; SafeFree(td6->maze_elements); - return 0; + return false; } x = location.x * 32; @@ -1059,14 +1061,14 @@ static bool track_design_save_to_td6_for_tracked_ride(uint8 rideIndex, rct_track for (sint32 station_index = 0; station_index < RCT12_MAX_STATIONS_PER_RIDE; station_index++) { z = ride->station_heights[station_index]; - LocationXY8 location; + TileCoordsXYZD location; if (i == 0) { - location = ride->entrances[station_index]; + location = ride_get_entrance_location(rideIndex, station_index); } else { - location = ride->exits[station_index]; + location = ride_get_exit_location(rideIndex, station_index); } - if (location.xy == RCT_XY8_UNDEFINED) { + if (location.isNull()) { continue; } diff --git a/src/openrct2/ride/TrackPaint.cpp b/src/openrct2/ride/TrackPaint.cpp index 4efcf3cbb8..4ec390e924 100644 --- a/src/openrct2/ride/TrackPaint.cpp +++ b/src/openrct2/ride/TrackPaint.cpp @@ -28,6 +28,7 @@ #include "TrackData.h" #include "RideData.h" #include "TrackPaint.h" +#include "Station.h" // clang-format off /* rct2: 0x007667AC */ @@ -225,11 +226,15 @@ bool track_paint_util_has_fence( break; } - uint16 entranceLoc = ((position.x / 32) + offset.x) | (((position.y / 32) + offset.y) * (1 << 8)); + sint32 entranceX = (position.x / 32) + offset.x; + sint32 entranceY = (position.y / 32) + offset.y; sint32 entranceId = tile_element_get_station(tileElement); + const TileCoordsXYZD entrance = ride_get_entrance_location(ride, entranceId); + const TileCoordsXYZD exit = ride_get_exit_location(ride, entranceId); - return (ride->entrances[entranceId].xy != entranceLoc && ride->exits[entranceId].xy != entranceLoc); + return ((entrance.x != entranceX || entrance.y != entranceY) && + (exit.x != entranceX || exit.y != entranceY)); } void track_paint_util_paint_floor(paint_session * session, uint8 edges, uint32 colourFlags, uint16 height, diff --git a/src/openrct2/ride/Vehicle.cpp b/src/openrct2/ride/Vehicle.cpp index 01b4027b27..5dbe123db4 100644 --- a/src/openrct2/ride/Vehicle.cpp +++ b/src/openrct2/ride/Vehicle.cpp @@ -1539,7 +1539,7 @@ static void vehicle_update_measurements(rct_vehicle * vehicle) } uint8 stationId = ride->current_test_station; - if (ride->entrances[stationId].xy != RCT_XY8_UNDEFINED) + if (!ride_get_entrance_location(ride, stationId).isNull()) { uint8 test_segment = ride->current_test_segment; @@ -1603,7 +1603,7 @@ static void vehicle_update_measurements(rct_vehicle * vehicle) ride->cur_test_track_z = vehicle->track_z / 8; ride->cur_test_track_location.xy = map_location; - if (ride->entrances[ride->current_test_station].xy == RCT_XY8_UNDEFINED) + if (ride_get_entrance_location(ride, ride->current_test_station).isNull()) return; uint16 track_elem_type = vehicle->track_type / 4; @@ -1813,7 +1813,7 @@ static void vehicle_update_measurements(rct_vehicle * vehicle) } } - if (ride->entrances[ride->current_test_station].xy == RCT_XY8_UNDEFINED) + if (ride_get_entrance_location(ride, ride->current_test_station).isNull()) return; sint16 x, y; @@ -2235,7 +2235,7 @@ static void vehicle_update_waiting_for_passengers(rct_vehicle * vehicle) if (!vehicle_open_restraints(vehicle)) return; - if (ride->entrances[vehicle->current_station].xy == RCT_XY8_UNDEFINED) + if (ride_get_entrance_location(ride, vehicle->current_station).isNull()) { ride->train_at_station[vehicle->current_station] = 0xFF; vehicle->sub_state = 2; @@ -2510,7 +2510,7 @@ static void vehicle_update_waiting_to_depart(rct_vehicle * vehicle) } else { - if (ride->exits[vehicle->current_station].xy != RCT_XY8_UNDEFINED) + if (!ride_get_exit_location(ride, vehicle->current_station).isNull()) { vehicle->status = VEHICLE_STATUS_UNLOADING_PASSENGERS; vehicle->sub_state = 0; @@ -2528,7 +2528,7 @@ static void vehicle_update_waiting_to_depart(rct_vehicle * vehicle) if (curVehicle->num_peeps != 0) { - if (ride->exits[vehicle->current_station].xy != RCT_XY8_UNDEFINED) + if (!ride_get_exit_location(ride, vehicle->current_station).isNull()) { vehicle->status = VEHICLE_STATUS_UNLOADING_PASSENGERS; vehicle->sub_state = 0; @@ -4114,7 +4114,7 @@ static void vehicle_update_unloading_passengers(rct_vehicle * vehicle) } else { - if (ride->exits[vehicle->current_station].xy == RCT_XY8_UNDEFINED) + if (ride_get_exit_location(ride, vehicle->current_station).isNull()) { if (vehicle->sub_state != 1) return; diff --git a/src/openrct2/world/Entrance.cpp b/src/openrct2/world/Entrance.cpp index 838502feb7..0ad7e4de50 100644 --- a/src/openrct2/world/Entrance.cpp +++ b/src/openrct2/world/Entrance.cpp @@ -26,6 +26,7 @@ #include "../localisation/StringIds.h" #include "../management/Finance.h" #include "../ride/Track.h" +#include "../ride/Station.h" bool gParkEntranceGhostExists = false; LocationXYZ16 gParkEntranceGhostPosition = { 0, 0, 0 }; @@ -193,7 +194,8 @@ static money32 RideEntranceExitPlace(sint16 x, if (isExit) { - if (ride->exits[stationNum].xy != RCT_XY8_UNDEFINED) + const auto exit = ride_get_exit_location(rideIndex, stationNum); + if (!exit.isNull()) { if (flags & GAME_COMMAND_FLAG_GHOST) { @@ -201,22 +203,26 @@ static money32 RideEntranceExitPlace(sint16 x, return MONEY32_UNDEFINED; } - removeCoord.x = ride->exits[stationNum].x * 32; - removeCoord.y = ride->exits[stationNum].y * 32; + removeCoord.x = exit.x * 32; + removeCoord.y = exit.y * 32; requiresRemove = true; } } - else if (ride->entrances[stationNum].xy != RCT_XY8_UNDEFINED) + else { - if (flags & GAME_COMMAND_FLAG_GHOST) + const auto entrance = ride_get_entrance_location(rideIndex, stationNum); + if (!entrance.isNull()) { - gGameCommandErrorText = 0; - return MONEY32_UNDEFINED; - } + if (flags & GAME_COMMAND_FLAG_GHOST) + { + gGameCommandErrorText = 0; + return MONEY32_UNDEFINED; + } - removeCoord.x = ride->entrances[stationNum].x * 32; - removeCoord.y = ride->entrances[stationNum].y * 32; - requiresRemove = true; + removeCoord.x = entrance.x * 32; + removeCoord.y = entrance.y * 32; + requiresRemove = true; + } } if (requiresRemove) @@ -296,13 +302,11 @@ static money32 RideEntranceExitPlace(sint16 x, if (isExit) { - ride->exits[stationNum].x = x / 32; - ride->exits[stationNum].y = y / 32; + ride_set_exit_location(ride, stationNum, { x / 32, y / 32, z / 8, (uint8)tile_element_get_direction(tileElement)}); } else { - ride->entrances[stationNum].x = x / 32; - ride->entrances[stationNum].y = y / 32; + ride_set_entrance_location(ride, stationNum, { x / 32, y / 32, z / 8, (uint8)tile_element_get_direction(tileElement)}); ride->last_peep_in_queue[stationNum] = SPRITE_INDEX_NULL; ride->queue_length[stationNum] = 0; @@ -384,7 +388,10 @@ static money32 RideEntranceExitRemove(sint16 x, sint16 y, uint8 rideIndex, uint8 if (tile_element_get_type(tileElement) != TILE_ELEMENT_TYPE_ENTRANCE) continue; - if (tileElement->base_height != ride->station_heights[stationNum]) + if (tile_element_get_ride_index(tileElement) != rideIndex) + continue; + + if (tile_element_get_station(tileElement) != stationNum) continue; if (flags & GAME_COMMAND_FLAG_5 && !(tileElement->flags & TILE_ELEMENT_FLAG_GHOST)) @@ -416,11 +423,11 @@ static money32 RideEntranceExitRemove(sint16 x, sint16 y, uint8 rideIndex, uint8 if (isExit) { - ride->exits[stationNum].xy = RCT_XY8_UNDEFINED; + ride_clear_exit_location(ride, stationNum); } else { - ride->entrances[stationNum].xy = RCT_XY8_UNDEFINED; + ride_clear_entrance_location(ride, stationNum); } footpath_update_queue_chains(); diff --git a/src/openrct2/world/Entrance.h b/src/openrct2/world/Entrance.h index a7b2b8cff7..39b64f76da 100644 --- a/src/openrct2/world/Entrance.h +++ b/src/openrct2/world/Entrance.h @@ -18,7 +18,7 @@ #define _ENTRANCE_H_ #include "../common.h" -#include "Location.h" +#include "Location.hpp" #pragma pack(push, 1) struct rct_entrance_type { diff --git a/src/openrct2/world/Footpath.cpp b/src/openrct2/world/Footpath.cpp index e82c6fca7f..4f5a293c16 100644 --- a/src/openrct2/world/Footpath.cpp +++ b/src/openrct2/world/Footpath.cpp @@ -1609,12 +1609,11 @@ void footpath_update_queue_chains() for (sint32 i = 0; i < MAX_STATIONS; i++) { - if (ride->entrances[i].xy == RCT_XY8_UNDEFINED) + TileCoordsXYZD location = ride_get_entrance_location(rideIndex, i); + if (location.isNull()) continue; - uint8 x = ride->entrances[i].x; - uint8 y = ride->entrances[i].y; - rct_tile_element * tileElement = map_get_first_element_at(x, y); + rct_tile_element * tileElement = map_get_first_element_at(location.x, location.y); do { if (tile_element_get_type(tileElement) != TILE_ELEMENT_TYPE_ENTRANCE) @@ -1625,7 +1624,7 @@ void footpath_update_queue_chains() continue; uint8 direction = tile_element_get_direction_with_offset(tileElement, 2); - footpath_chain_ride_queue(rideIndex, i, x << 5, y << 5, tileElement, direction); + footpath_chain_ride_queue(rideIndex, i, location.x << 5, location.y << 5, tileElement, direction); } while (!tile_element_is_last_for_tile(tileElement++)); } } diff --git a/src/openrct2/world/Location.h b/src/openrct2/world/Location.hpp similarity index 92% rename from src/openrct2/world/Location.h rename to src/openrct2/world/Location.hpp index 680719e077..4dbc172111 100644 --- a/src/openrct2/world/Location.h +++ b/src/openrct2/world/Location.hpp @@ -45,6 +45,9 @@ struct LocationXYZ16 { assert_struct_size(LocationXYZ16, 6); #pragma pack(pop) +constexpr sint32 COORDS_NULL = -1; + + /* * Tile coordinates use 1 x/y increment per tile. * Regular ('big', 'sprite') coordinates use 32 x/y increments per tile. @@ -73,12 +76,16 @@ struct TileCoordsXYZD { sint32 x, y, z; uint8 direction; + + bool isNull() const { return x == COORDS_NULL; }; }; struct CoordsXYZD { sint32 x, y, z; uint8 direction; + + bool isNull() const { return x == COORDS_NULL; }; }; diff --git a/src/openrct2/world/Map.h b/src/openrct2/world/Map.h index 7c605a67d5..0e941b468c 100644 --- a/src/openrct2/world/Map.h +++ b/src/openrct2/world/Map.h @@ -19,7 +19,7 @@ #include #include "../common.h" -#include "Location.h" +#include "Location.hpp" #pragma pack(push, 1) struct rct_tile_element_surface_properties { diff --git a/src/openrct2/world/TileInspector.cpp b/src/openrct2/world/TileInspector.cpp index 5a826c36f6..1b1b929aff 100644 --- a/src/openrct2/world/TileInspector.cpp +++ b/src/openrct2/world/TileInspector.cpp @@ -26,6 +26,7 @@ #include "Footpath.h" #include "Map.h" #include "TileInspector.h" +#include "../ride/Station.h" uint32 windowTileInspectorTileX; uint32 windowTileInspectorTileY; @@ -248,9 +249,34 @@ sint32 tile_inspector_rotate_element_at(sint32 x, sint32 y, sint32 elementIndex, tileElement->properties.path.edges |= ((pathEdges << 1) | (pathEdges >> 3)) & 0x0F; tileElement->properties.path.edges |= ((pathCorners << 1) | (pathCorners >> 3)) & 0xF0; break; + case TILE_ELEMENT_TYPE_ENTRANCE: + { + // Update element rotation + newRotation = tile_element_get_direction_with_offset(tileElement, 1); + tileElement->type &= ~TILE_ELEMENT_DIRECTION_MASK; + tileElement->type |= newRotation; + + // Update ride's known entrance/exit rotation + Ride * ride = get_ride(tileElement->properties.entrance.ride_index); + uint8 stationIndex = tileElement->properties.entrance.index; + auto entrance = ride_get_entrance_location(ride, stationIndex); + auto exit = ride_get_exit_location(ride, stationIndex); + uint8 entranceType = entrance_element_get_type(tileElement); + uint8 z = tileElement->base_height; + + // Make sure this is the correct entrance or exit + if (entranceType == ENTRANCE_TYPE_RIDE_ENTRANCE && entrance.x == x && entrance.y == y && entrance.z == z) + { + ride_set_entrance_location(ride, stationIndex, { entrance.x, entrance.y, entrance.z, newRotation }); + } + else if (entranceType == ENTRANCE_TYPE_RIDE_EXIT && exit.x == x && exit.y == y && exit.z == z) + { + ride_set_exit_location(ride, stationIndex, { exit.x, exit.y, exit.z, newRotation }); + } + break; + } case TILE_ELEMENT_TYPE_TRACK: case TILE_ELEMENT_TYPE_SMALL_SCENERY: - case TILE_ELEMENT_TYPE_ENTRANCE: case TILE_ELEMENT_TYPE_WALL: newRotation = tile_element_get_direction_with_offset(tileElement, 1); tileElement->type &= ~TILE_ELEMENT_DIRECTION_MASK; @@ -389,6 +415,28 @@ sint32 tile_inspector_any_base_height_offset(sint32 x, sint32 y, sint16 elementI if (flags & GAME_COMMAND_FLAG_APPLY) { + if (tile_element_get_type(tileElement) == TILE_ELEMENT_TYPE_ENTRANCE) + { + uint8 entranceType = tileElement->properties.entrance.type; + if (entranceType != ENTRANCE_TYPE_PARK_ENTRANCE) + { + // Update the ride's known entrance or exit height + Ride * ride = get_ride(tileElement->properties.entrance.ride_index); + uint8 entranceIndex = tileElement->properties.entrance.index; + auto entrance = ride_get_entrance_location(ride, entranceIndex); + auto exit = ride_get_exit_location(ride, entranceIndex); + uint8 z = tileElement->base_height; + + // Make sure this is the correct entrance or exit + if (entranceType == ENTRANCE_TYPE_RIDE_ENTRANCE && entrance.x == x && entrance.y == y && entrance.z == z) + ride_set_entrance_location( + ride, entranceIndex, { entrance.x, entrance.y, z + heightOffset, entrance.direction }); + else if (entranceType == ENTRANCE_TYPE_RIDE_EXIT && exit.x == x && exit.y == y && exit.z == z) + ride_set_exit_location( + ride, entranceIndex, { exit.x, exit.y, z + heightOffset, exit.direction }); + } + } + tileElement->base_height += heightOffset; tileElement->clearance_height += heightOffset; @@ -600,15 +648,10 @@ sint32 tile_inspector_entrance_make_usable(sint32 x, sint32 y, sint32 elementInd switch (entranceElement->properties.entrance.type) { case ENTRANCE_TYPE_RIDE_ENTRANCE: - ride->entrances[stationIndex].x = x; - ride->entrances[stationIndex].y = y; + ride_set_entrance_location(ride, stationIndex, { x, y, entranceElement->base_height, (uint8)tile_element_get_direction(entranceElement) }); break; case ENTRANCE_TYPE_RIDE_EXIT: - ride->exits[stationIndex].x = x; - ride->exits[stationIndex].y = y; - - // TODO: Remove once mechanics don't assume exits always match the station heights - ride->station_heights[stationIndex] = entranceElement->base_height; + ride_set_exit_location(ride, stationIndex, { x, y, entranceElement->base_height, (uint8)tile_element_get_direction(entranceElement) }); break; } diff --git a/test/testpaint/Compat.cpp b/test/testpaint/Compat.cpp index a75c3afb3e..091191c6d6 100644 --- a/test/testpaint/Compat.cpp +++ b/test/testpaint/Compat.cpp @@ -50,6 +50,9 @@ const CoordsXY TileDirectionDelta[] = { {-32, -32} }; +TileCoordsXYZD ride_get_entrance_location(const Ride * ride, const sint32 stationIndex); +TileCoordsXYZD ride_get_exit_location(const Ride * ride, const sint32 stationIndex); + uint8 get_current_rotation() { return gCurrentRotation & 3; } @@ -294,3 +297,13 @@ void track_element_clear_cable_lift(rct_tile_element * trackElement) { trackElement->properties.track.colour &= ~TRACK_ELEMENT_COLOUR_FLAG_CABLE_LIFT; } + +TileCoordsXYZD ride_get_entrance_location(const Ride * ride, const sint32 stationIndex) +{ + return ride->entrances[stationIndex]; +} + +TileCoordsXYZD ride_get_exit_location(const Ride * ride, const sint32 stationIndex) +{ + return ride->exits[stationIndex]; +} \ No newline at end of file