diff --git a/CMakeLists.txt b/CMakeLists.txt index 10c5a523ea..f5a817fa73 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.52") +set(REPLAYS_VERSION "0.0.53") set(REPLAYS_URL "https://github.com/OpenRCT2/replays/releases/download/v${REPLAYS_VERSION}/replays.zip") -set(REPLAYS_SHA1 "3A1A6B5B25ACA3B8AADC618A9D2BE44F8A23A7BB") +set(REPLAYS_SHA1 "8DDA5F2CC0B101D477396A3B016FF5F3EDFD074F") option(FORCE32 "Force 32-bit build. It will add `-m32` to compiler flags.") option(WITH_TESTS "Build tests") diff --git a/openrct2.proj b/openrct2.proj index 2dad3d4aec..aa87bd36bd 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.52/replays.zip - 3A1A6B5B25ACA3B8AADC618A9D2BE44F8A23A7BB + https://github.com/OpenRCT2/replays/releases/download/v0.0.53/replays.zip + 8DDA5F2CC0B101D477396A3B016FF5F3EDFD074F diff --git a/src/openrct2-ui/interface/Window.cpp b/src/openrct2-ui/interface/Window.cpp index 14aee560f7..7ffc99deb4 100644 --- a/src/openrct2-ui/interface/Window.cpp +++ b/src/openrct2-ui/interface/Window.cpp @@ -274,7 +274,7 @@ rct_window* WindowCreate( w->min_height = height; w->max_height = height; - w->focus2 = std::nullopt; + w->focus = std::nullopt; w->page = 0; w->var_48C = 0; w->var_492 = 0; diff --git a/src/openrct2-ui/scripting/CustomWindow.cpp b/src/openrct2-ui/scripting/CustomWindow.cpp index 4e01689373..874427ef14 100644 --- a/src/openrct2-ui/scripting/CustomWindow.cpp +++ b/src/openrct2-ui/scripting/CustomWindow.cpp @@ -786,8 +786,7 @@ namespace OpenRCT2::Ui::Windows auto wheight = viewportWidget->height() - 1; if (viewport == nullptr) { - const auto focus = Focus2(CoordsXYZ(0, 0, 0)); - viewport_create(this, { left, top }, wwidth, wheight, focus); + viewport_create(this, { left, top }, wwidth, wheight, Focus(CoordsXYZ(0, 0, 0))); flags |= WF_NO_SCROLLING; Invalidate(); } diff --git a/src/openrct2-ui/windows/Banner.cpp b/src/openrct2-ui/windows/Banner.cpp index 3959bc29de..79310f0f81 100644 --- a/src/openrct2-ui/windows/Banner.cpp +++ b/src/openrct2-ui/windows/Banner.cpp @@ -79,10 +79,9 @@ private: void CreateViewport() { rct_widget* viewportWidget = &window_banner_widgets[WIDX_VIEWPORT]; - const auto focus = Focus2(_bannerViewPos); viewport_create( this, windowPos + ScreenCoordsXY{ viewportWidget->left + 1, viewportWidget->top + 1 }, - (viewportWidget->width()) - 1, (viewportWidget->height()) - 1, focus); + (viewportWidget->width()) - 1, (viewportWidget->height()) - 1, Focus(_bannerViewPos)); if (viewport != nullptr) viewport->flags = gConfigGeneral.always_show_gridlines ? VIEWPORT_FLAG_GRIDLINES : 0; @@ -97,7 +96,7 @@ private: return nullptr; } - TileElement* tileElement = map_get_first_element_at(banner->position.ToCoordsXY().ToTileCentre()); + TileElement* tileElement = map_get_first_element_at(banner->position); if (tileElement == nullptr) { return nullptr; diff --git a/src/openrct2-ui/windows/EditorMain.cpp b/src/openrct2-ui/windows/EditorMain.cpp index 121b8e4ac3..d0186f17db 100644 --- a/src/openrct2-ui/windows/EditorMain.cpp +++ b/src/openrct2-ui/windows/EditorMain.cpp @@ -40,8 +40,7 @@ rct_window* window_editor_main_open() &window_editor_main_events, WC_MAIN_WINDOW, WF_STICK_TO_BACK); window->widgets = window_editor_main_widgets; - const auto focus = Focus2(CoordsXYZ(0x0FFF, 0x0FFF, 0)); - viewport_create(window, window->windowPos, window->width, window->height, focus); + viewport_create(window, window->windowPos, window->width, window->height, Focus(CoordsXYZ(0x0FFF, 0x0FFF, 0))); window->viewport->flags |= 0x0400; gCurrentRotation = 0; diff --git a/src/openrct2-ui/windows/Guest.cpp b/src/openrct2-ui/windows/Guest.cpp index c7446b80c5..c7063690af 100644 --- a/src/openrct2-ui/windows/Guest.cpp +++ b/src/openrct2-ui/windows/Guest.cpp @@ -732,7 +732,7 @@ void window_guest_viewport_init(rct_window* w) uint16_t origViewportFlags{}; if (w->viewport != nullptr) { - if (w->focus2.has_value()) + if (w->focus.has_value()) return; origViewportFlags = w->viewport->flags; @@ -750,7 +750,7 @@ void window_guest_viewport_init(rct_window* w) int32_t width = view_widget->width() - 1; int32_t height = view_widget->height() - 1; - viewport_create(w, screenPos, width, height, w->focus2.value()); + viewport_create(w, screenPos, width, height, w->focus.value()); if (w->viewport != nullptr && reCreateViewport) { w->viewport->flags = origViewportFlags; diff --git a/src/openrct2-ui/windows/Main.cpp b/src/openrct2-ui/windows/Main.cpp index 347f2cc49f..ed7bab0503 100644 --- a/src/openrct2-ui/windows/Main.cpp +++ b/src/openrct2-ui/windows/Main.cpp @@ -41,8 +41,7 @@ rct_window* window_main_open() WF_STICK_TO_BACK); window->widgets = window_main_widgets; - const auto focus = Focus2(CoordsXYZ(0x0FFF, 0x0FFF, 0)); - viewport_create(window, window->windowPos, window->width, window->height, focus); + viewport_create(window, window->windowPos, window->width, window->height, Focus(CoordsXYZ(0x0FFF, 0x0FFF, 0))); window->viewport->flags |= VIEWPORT_FLAG_SOUND_ON; gCurrentRotation = 0; gShowGridLinesRefCount = 0; diff --git a/src/openrct2-ui/windows/Park.cpp b/src/openrct2-ui/windows/Park.cpp index 6b477ad3b4..9f3bf92f0d 100644 --- a/src/openrct2-ui/windows/Park.cpp +++ b/src/openrct2-ui/windows/Park.cpp @@ -740,11 +740,11 @@ static void window_park_init_viewport(rct_window* w) if (w->page != WINDOW_PARK_PAGE_ENTRANCE) return; - std::optional focus = std::nullopt; + std::optional focus = std::nullopt; if (!gParkEntrances.empty()) { const auto& entrance = gParkEntrances[0]; - focus = Focus2(CoordsXYZ{ entrance.x + 16, entrance.y + 16, entrance.z + 32 }); + focus = Focus(CoordsXYZ{ entrance.x + 16, entrance.y + 16, entrance.z + 32 }); } if (w->viewport == nullptr) @@ -760,7 +760,7 @@ static void window_park_init_viewport(rct_window* w) // Call invalidate event window_event_invalidate_call(w); - w->focus2 = focus; + w->focus = focus; if (focus.has_value()) { diff --git a/src/openrct2-ui/windows/Player.cpp b/src/openrct2-ui/windows/Player.cpp index fab5a3df40..9a6c6352de 100644 --- a/src/openrct2-ui/windows/Player.cpp +++ b/src/openrct2-ui/windows/Player.cpp @@ -547,7 +547,7 @@ static void window_player_set_page(rct_window* w, int32_t page) { if (w->viewport == nullptr) { - const auto focus = Focus2(TileCoordsXYZ(128, 128, 0).ToCoordsXYZ()); + const auto focus = Focus(TileCoordsXYZ(128, 128, 0).ToCoordsXYZ()); viewport_create(w, w->windowPos, w->width, w->height, focus); w->flags |= WF_NO_SCROLLING; window_event_invalidate_call(w); diff --git a/src/openrct2-ui/windows/Ride.cpp b/src/openrct2-ui/windows/Ride.cpp index ec0286cbb8..1f2d68054b 100644 --- a/src/openrct2-ui/windows/Ride.cpp +++ b/src/openrct2-ui/windows/Ride.cpp @@ -1589,7 +1589,7 @@ static void window_ride_init_viewport(rct_window* w) int32_t viewSelectionIndex = w->ride.view - 1; - std::optional focus; + std::optional focus; if (viewSelectionIndex >= 0 && viewSelectionIndex < ride->num_vehicles && ride->lifecycle_flags & RIDE_LIFECYCLE_ON_TRACK) { @@ -1609,7 +1609,7 @@ static void window_ride_init_viewport(rct_window* w) } if (vehId != SPRITE_INDEX_NULL) { - focus = Focus2(vehId); + focus = Focus(vehId); } } else if (viewSelectionIndex >= ride->num_vehicles && viewSelectionIndex < (ride->num_vehicles + ride->num_stations)) @@ -1618,7 +1618,7 @@ static void window_ride_init_viewport(rct_window* w) if (stationIndex) { const auto location = ride->stations[*stationIndex].GetStart(); - focus = Focus2(location); + focus = Focus(location); } } else @@ -1630,14 +1630,14 @@ static void window_ride_init_viewport(rct_window* w) if (w->number < ride_overall_views.size()) { const auto& view = ride_overall_views[w->number]; - focus = Focus2(view.loc, view.zoom); + focus = Focus(view.loc, view.zoom); } } uint16_t viewport_flags = 0; if (w->viewport != nullptr) { - if (focus == w->focus2) + if (focus == w->focus) { return; } @@ -1651,7 +1651,7 @@ static void window_ride_init_viewport(rct_window* w) window_event_invalidate_call(w); - w->focus2 = focus; + w->focus = focus; // rct2: 0x006aec9c only used here so brought it into the function if (!w->viewport && !ride->overall_view.IsNull()) @@ -1662,7 +1662,7 @@ static void window_ride_init_viewport(rct_window* w) int32_t width = view_widget->width() - 1; int32_t height = view_widget->height() - 1; - viewport_create(w, screenPos, width, height, w->focus2.value()); + viewport_create(w, screenPos, width, height, w->focus.value()); w->flags |= WF_NO_SCROLLING; w->Invalidate(); @@ -1796,6 +1796,8 @@ static void window_ride_main_resize(rct_window* w) w->flags |= WF_RESIZABLE; window_set_resize(w, 316, minHeight, 500, 450); + // Unlike with other windows, the focus needs to be recentred so it’s best to just reset it. + w->focus = std::nullopt; window_ride_init_viewport(w); } diff --git a/src/openrct2-ui/windows/RideConstruction.cpp b/src/openrct2-ui/windows/RideConstruction.cpp index 6d252746dc..8a34c04e84 100644 --- a/src/openrct2-ui/windows/RideConstruction.cpp +++ b/src/openrct2-ui/windows/RideConstruction.cpp @@ -2424,11 +2424,11 @@ static void sub_6CBCE2( auto southTileCoords = centreTileCoords + TileDirectionDelta[TILE_ELEMENT_DIRECTION_SOUTH]; // Replace map elements with temporary ones containing track - _backupTileElementArrays[0] = map_get_first_element_at(centreTileCoords.ToCoordsXY()); - _backupTileElementArrays[1] = map_get_first_element_at(eastTileCoords.ToCoordsXY()); - _backupTileElementArrays[2] = map_get_first_element_at(westTileCoords.ToCoordsXY()); - _backupTileElementArrays[3] = map_get_first_element_at(northTileCoords.ToCoordsXY()); - _backupTileElementArrays[4] = map_get_first_element_at(southTileCoords.ToCoordsXY()); + _backupTileElementArrays[0] = map_get_first_element_at(centreTileCoords); + _backupTileElementArrays[1] = map_get_first_element_at(eastTileCoords); + _backupTileElementArrays[2] = map_get_first_element_at(westTileCoords); + _backupTileElementArrays[3] = map_get_first_element_at(northTileCoords); + _backupTileElementArrays[4] = map_get_first_element_at(southTileCoords); map_set_tile_element(centreTileCoords, &_tempTrackTileElement); map_set_tile_element(eastTileCoords, &_tempSideTrackTileElement); map_set_tile_element(westTileCoords, &_tempSideTrackTileElement); diff --git a/src/openrct2-ui/windows/Sign.cpp b/src/openrct2-ui/windows/Sign.cpp index bddfd0dd20..b111f95c9b 100644 --- a/src/openrct2-ui/windows/Sign.cpp +++ b/src/openrct2-ui/windows/Sign.cpp @@ -127,10 +127,9 @@ public: // Create viewport rct_widget& viewportWidget = window_sign_widgets[WIDX_VIEWPORT]; - const auto focus = Focus2(CoordsXYZ{ signViewPosition, viewZ }); viewport_create( this, windowPos + ScreenCoordsXY{ viewportWidget.left + 1, viewportWidget.top + 1 }, viewportWidget.width() - 1, - viewportWidget.height() - 1, focus); + viewportWidget.height() - 1, Focus(CoordsXYZ{ signViewPosition, viewZ })); viewport->flags = gConfigGeneral.always_show_gridlines ? VIEWPORT_FLAG_GRIDLINES : 0; Invalidate(); @@ -300,10 +299,9 @@ public: // Create viewport rct_widget* viewportWidget = &window_sign_widgets[WIDX_VIEWPORT]; - const auto focus = Focus2(CoordsXYZ{ signViewPos }); viewport_create( this, windowPos + ScreenCoordsXY{ viewportWidget->left + 1, viewportWidget->top + 1 }, viewportWidget->width() - 1, - viewportWidget->height() - 1, focus); + viewportWidget->height() - 1, Focus(CoordsXYZ{ signViewPos })); if (viewport != nullptr) viewport->flags = gConfigGeneral.always_show_gridlines ? VIEWPORT_FLAG_GRIDLINES : 0; Invalidate(); diff --git a/src/openrct2-ui/windows/Staff.cpp b/src/openrct2-ui/windows/Staff.cpp index 6156c1cd5e..89da4d7b59 100644 --- a/src/openrct2-ui/windows/Staff.cpp +++ b/src/openrct2-ui/windows/Staff.cpp @@ -1339,7 +1339,7 @@ void window_staff_viewport_init(rct_window* w) if (w->page != WINDOW_STAFF_OVERVIEW) return; - std::optional focus; + std::optional focus; const auto peep = GetStaff(w); if (peep == nullptr) @@ -1349,14 +1349,14 @@ void window_staff_viewport_init(rct_window* w) if (peep->State != PeepState::Picked) { - focus = Focus2(peep->sprite_index); + focus = Focus(peep->sprite_index); } uint16_t viewport_flags; if (w->viewport) { - if (focus == w->focus2) + if (focus == w->focus) return; viewport_flags = w->viewport->flags; @@ -1371,7 +1371,7 @@ void window_staff_viewport_init(rct_window* w) window_event_invalidate_call(w); - w->focus2 = focus; + w->focus = focus; if (peep->State != PeepState::Picked) { diff --git a/src/openrct2-ui/windows/TitleCommandEditor.cpp b/src/openrct2-ui/windows/TitleCommandEditor.cpp index 4b15b97904..b02e3fc1a3 100644 --- a/src/openrct2-ui/windows/TitleCommandEditor.cpp +++ b/src/openrct2-ui/windows/TitleCommandEditor.cpp @@ -227,7 +227,7 @@ void window_title_command_editor_open(TitleSequence* sequence, int32_t index, bo WindowInitScrollWidgets(window); rct_widget* const viewportWidget = &window_title_command_editor_widgets[WIDX_VIEWPORT]; - const auto focus = Focus2(CoordsXYZ{ 0, 0, 0 }); + const auto focus = Focus(CoordsXYZ{ 0, 0, 0 }); viewport_create( window, window->windowPos + ScreenCoordsXY{ viewportWidget->left + 1, viewportWidget->top + 1 }, viewportWidget->width() - 1, viewportWidget->height() - 1, focus); diff --git a/src/openrct2-ui/windows/Viewport.cpp b/src/openrct2-ui/windows/Viewport.cpp index abcd712170..66ee0f3a33 100644 --- a/src/openrct2-ui/windows/Viewport.cpp +++ b/src/openrct2-ui/windows/Viewport.cpp @@ -76,8 +76,7 @@ public: enabled_widgets = (1ULL << WIDX_CLOSE) | (1ULL << WIDX_ZOOM_IN) | (1ULL << WIDX_ZOOM_OUT) | (1ULL << WIDX_LOCATE); // Create viewport - const auto focus = Focus2(TileCoordsXYZ(128, 128, 0).ToCoordsXYZ()); - viewport_create(this, windowPos, width, height, focus); + viewport_create(this, windowPos, width, height, Focus(TileCoordsXYZ(128, 128, 0).ToCoordsXYZ())); if (viewport == nullptr) { Close(); diff --git a/src/openrct2/GameState.cpp b/src/openrct2/GameState.cpp index 463405558a..53b1e9b7c5 100644 --- a/src/openrct2/GameState.cpp +++ b/src/openrct2/GameState.cpp @@ -56,6 +56,7 @@ GameState::GameState() void GameState::InitAll(int32_t mapSize) { gInMapInitCode = true; + gCurrentTicks = 0; gCurrentTicks = 0; map_init(mapSize); diff --git a/src/openrct2/actions/ClearAction.cpp b/src/openrct2/actions/ClearAction.cpp index cfeea2f993..bccba7e5a7 100644 --- a/src/openrct2/actions/ClearAction.cpp +++ b/src/openrct2/actions/ClearAction.cpp @@ -214,7 +214,7 @@ void ClearAction::ResetClearLargeSceneryFlag() { for (int32_t x = 0; x < MAXIMUM_MAP_SIZE_TECHNICAL; x++) { - auto tileElement = map_get_first_element_at(TileCoordsXY{ x, y }.ToCoordsXY()); + auto tileElement = map_get_first_element_at(TileCoordsXY{ x, y }); do { if (tileElement == nullptr) diff --git a/src/openrct2/interface/Viewport.cpp b/src/openrct2/interface/Viewport.cpp index 65e093703f..28cab048bd 100644 --- a/src/openrct2/interface/Viewport.cpp +++ b/src/openrct2/interface/Viewport.cpp @@ -117,14 +117,14 @@ std::optional centre_2d_coordinates(const CoordsXYZ& loc, rct_vi return { screenCoord }; } -CoordsXYZ Focus2::GetPos() const +CoordsXYZ Focus::GetPos() const { return std::visit( [](auto&& arg) { using T = std::decay_t; - if constexpr (std::is_same_v) + if constexpr (std::is_same_v) return arg; - else if constexpr (std::is_same_v) + else if constexpr (std::is_same_v) { auto* centreEntity = GetEntity(arg); if (centreEntity != nullptr) @@ -158,7 +158,7 @@ CoordsXYZ Focus2::GetPos() const * flags: edx top most 2 bits 0b_X1 for zoom clear see below for 2nd bit. * w: esi */ -void viewport_create(rct_window* w, const ScreenCoordsXY& screenCoords, int32_t width, int32_t height, const Focus2& focus) +void viewport_create(rct_window* w, const ScreenCoordsXY& screenCoords, int32_t width, int32_t height, const Focus& focus) { rct_viewport* viewport = nullptr; if (_viewports.size() >= MAX_VIEWPORT_COUNT) @@ -188,9 +188,9 @@ void viewport_create(rct_window* w, const ScreenCoordsXY& screenCoords, int32_t w->viewport_target_sprite = std::visit( [](auto&& arg) { using T = std::decay_t; - if constexpr (std::is_same_v) + if constexpr (std::is_same_v) return SPRITE_INDEX_NULL; - else if constexpr (std::is_same_v) + else if constexpr (std::is_same_v) return arg; }, focus.data); @@ -702,7 +702,7 @@ void viewport_update_smart_sprite_follow(rct_window* window) break; default: // All other types don't need any "smart" following; steam particle, duck, money effect, etc. - window->focus2 = Focus2(window->viewport_smart_follow_sprite); + window->focus = Focus(window->viewport_smart_follow_sprite); window->viewport_target_sprite = window->viewport_smart_follow_sprite; break; } @@ -710,14 +710,14 @@ void viewport_update_smart_sprite_follow(rct_window* window) void viewport_update_smart_guest_follow(rct_window* window, const Guest* peep) { - Focus2 focus = Focus2(peep->sprite_index); + Focus focus = Focus(peep->sprite_index); window->viewport_target_sprite = peep->sprite_index; if (peep->State == PeepState::Picked) { window->viewport_smart_follow_sprite = SPRITE_INDEX_NULL; window->viewport_target_sprite = SPRITE_INDEX_NULL; - window->focus2 = std::nullopt; // No focus + window->focus = std::nullopt; // No focus return; } @@ -734,7 +734,7 @@ void viewport_update_smart_guest_follow(rct_window* window, const Guest* peep) const auto car = train->GetCar(peep->CurrentCar); if (car != nullptr) { - focus = Focus2(car->sprite_index); + focus = Focus(car->sprite_index); overallFocus = false; window->viewport_target_sprite = car->sprite_index; } @@ -752,12 +752,12 @@ void viewport_update_smart_guest_follow(rct_window* window, const Guest* peep) coordFocus.x = xy.x; coordFocus.y = xy.y; coordFocus.z = tile_element_height(xy) + (4 * COORDS_Z_STEP); - focus = Focus2(coordFocus); + focus = Focus(coordFocus); window->viewport_target_sprite = SPRITE_INDEX_NULL; } } - window->focus2 = focus; + window->focus = focus; } void viewport_update_smart_staff_follow(rct_window* window, const Staff* peep) @@ -766,17 +766,17 @@ void viewport_update_smart_staff_follow(rct_window* window, const Staff* peep) { window->viewport_smart_follow_sprite = SPRITE_INDEX_NULL; window->viewport_target_sprite = SPRITE_INDEX_NULL; - window->focus2 = std::nullopt; + window->focus = std::nullopt; return; } - window->focus2 = Focus2(window->viewport_smart_follow_sprite); + window->focus = Focus(window->viewport_smart_follow_sprite); window->viewport_target_sprite = window->viewport_smart_follow_sprite; } void viewport_update_smart_vehicle_follow(rct_window* window) { - window->focus2 = Focus2(window->viewport_smart_follow_sprite); + window->focus = Focus(window->viewport_smart_follow_sprite); window->viewport_target_sprite = window->viewport_smart_follow_sprite; } diff --git a/src/openrct2/interface/Viewport.h b/src/openrct2/interface/Viewport.h index d9b22283ac..697eb65510 100644 --- a/src/openrct2/interface/Viewport.h +++ b/src/openrct2/interface/Viewport.h @@ -104,7 +104,7 @@ extern uint8_t gCurrentRotation; void viewport_init_all(); std::optional centre_2d_coordinates(const CoordsXYZ& loc, rct_viewport* viewport); -void viewport_create(rct_window* w, const ScreenCoordsXY& screenCoords, int32_t width, int32_t height, const Focus2& focus); +void viewport_create(rct_window* w, const ScreenCoordsXY& screenCoords, int32_t width, int32_t height, const Focus& focus); void viewport_remove(rct_viewport* viewport); void viewports_invalidate(int32_t left, int32_t top, int32_t right, int32_t bottom, int32_t maxZoom = -1); void viewport_update_position(rct_window* window); diff --git a/src/openrct2/interface/Window.h b/src/openrct2/interface/Window.h index b78a0b1d48..e498a21691 100644 --- a/src/openrct2/interface/Window.h +++ b/src/openrct2/interface/Window.h @@ -195,7 +195,7 @@ struct rct_scroll constexpr auto WINDOW_SCROLL_UNDEFINED = std::numeric_limits::max(); -struct Focus2 +struct Focus { using CoordinateFocus = CoordsXYZ; using EntityFocus = uint16_t; @@ -203,7 +203,7 @@ struct Focus2 uint8_t zoom = 0; std::variant data; - template constexpr explicit Focus2(T newValue, uint8_t newZoom = 0) + template constexpr explicit Focus(T newValue, uint8_t newZoom = 0) { data = newValue; zoom = newZoom; @@ -211,7 +211,7 @@ struct Focus2 CoordsXYZ GetPos() const; - constexpr bool operator==(const Focus2& other) const + constexpr bool operator==(const Focus& other) const { if (zoom != other.zoom) { @@ -219,7 +219,7 @@ struct Focus2 } return data == other.data; } - constexpr bool operator!=(const Focus2& other) const + constexpr bool operator!=(const Focus& other) const { return !(*this == other); } diff --git a/src/openrct2/interface/Window_internal.cpp b/src/openrct2/interface/Window_internal.cpp index 576212edc7..35aaa071db 100644 --- a/src/openrct2/interface/Window_internal.cpp +++ b/src/openrct2/interface/Window_internal.cpp @@ -12,10 +12,10 @@ void rct_window::SetLocation(const CoordsXYZ& coords) void rct_window::ScrollToViewport() { - if (viewport == nullptr || !focus2.has_value()) + if (viewport == nullptr || !focus.has_value()) return; - CoordsXYZ newCoords = focus2.value().GetPos(); + CoordsXYZ newCoords = focus.value().GetPos(); auto mainWindow = window_get_main(); if (mainWindow != nullptr) diff --git a/src/openrct2/interface/Window_internal.h b/src/openrct2/interface/Window_internal.h index 444bde6e44..24b2796636 100644 --- a/src/openrct2/interface/Window_internal.h +++ b/src/openrct2/interface/Window_internal.h @@ -55,7 +55,7 @@ struct rct_window uint32_t list_item_positions[1024]{}; uint16_t no_list_items{}; // 0 for no items int16_t selected_list_item{}; // -1 for none selected - std::optional focus2; + std::optional focus; union { campaign_variables campaign; diff --git a/src/openrct2/libopenrct2.vcxproj b/src/openrct2/libopenrct2.vcxproj index f88e448eb1..217ff1257f 100644 --- a/src/openrct2/libopenrct2.vcxproj +++ b/src/openrct2/libopenrct2.vcxproj @@ -310,12 +310,15 @@ + + + @@ -332,6 +335,7 @@ + @@ -356,6 +360,7 @@ + @@ -396,7 +401,9 @@ + + diff --git a/src/openrct2/network/NetworkBase.cpp b/src/openrct2/network/NetworkBase.cpp index 3235d87a56..364bcbcff9 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 "9" +#define NETWORK_STREAM_VERSION "10" #define NETWORK_STREAM_ID OPENRCT2_VERSION "-" NETWORK_STREAM_VERSION static Peep* _pickup_peep = nullptr; diff --git a/src/openrct2/peep/GuestPathfinding.cpp b/src/openrct2/peep/GuestPathfinding.cpp index 68582bfa2b..2f27e93843 100644 --- a/src/openrct2/peep/GuestPathfinding.cpp +++ b/src/openrct2/peep/GuestPathfinding.cpp @@ -276,7 +276,7 @@ static uint8_t footpath_element_next_in_direction(TileCoordsXYZ loc, PathElement } loc += TileDirectionDelta[chosenDirection]; - nextTileElement = map_get_first_element_at(loc.ToCoordsXY()); + nextTileElement = map_get_first_element_at(loc); do { if (nextTileElement == nullptr) @@ -327,7 +327,7 @@ static uint8_t footpath_element_dest_in_dir( return PATH_SEARCH_LIMIT_REACHED; loc += TileDirectionDelta[chosenDirection]; - tileElement = map_get_first_element_at(loc.ToCoordsXY()); + tileElement = map_get_first_element_at(loc); if (tileElement == nullptr) { return PATH_SEARCH_FAILED; @@ -733,7 +733,7 @@ static void peep_pathfind_heuristic_search( /* Get the next map element of interest in the direction of test_edge. */ bool found = false; - TileElement* tileElement = map_get_first_element_at(loc.ToCoordsXY()); + TileElement* tileElement = map_get_first_element_at(loc); if (tileElement == nullptr) { return; @@ -1275,7 +1275,7 @@ Direction peep_pathfind_choose_direction(const TileCoordsXYZ& loc, Peep* peep) #endif // defined(DEBUG_LEVEL_1) && DEBUG_LEVEL_1 // Get the path element at this location - TileElement* dest_tile_element = map_get_first_element_at(loc.ToCoordsXY()); + TileElement* dest_tile_element = map_get_first_element_at(loc); /* Where there are multiple matching map elements placed with zero * clearance, save the first one for later use to determine the path * slope - this maintains the original behaviour (which only processes @@ -1797,7 +1797,7 @@ static int32_t guest_path_find_park_entrance(Peep* peep, uint8_t edges) static void get_ride_queue_end(TileCoordsXYZ& loc) { TileCoordsXY queueEnd = { 0, 0 }; - TileElement* tileElement = map_get_first_element_at(loc.ToCoordsXY()); + TileElement* tileElement = map_get_first_element_at(loc); if (tileElement == nullptr) { @@ -1845,7 +1845,7 @@ static void get_ride_queue_end(TileCoordsXYZ& loc) } nextTile += TileDirectionDelta[direction]; - tileElement = map_get_first_element_at(nextTile.ToCoordsXY()); + tileElement = map_get_first_element_at(nextTile); found = false; if (tileElement == nullptr) break; diff --git a/src/openrct2/peep/Peep.cpp b/src/openrct2/peep/Peep.cpp index caa3ef398e..71c27737e2 100644 --- a/src/openrct2/peep/Peep.cpp +++ b/src/openrct2/peep/Peep.cpp @@ -711,7 +711,7 @@ void Peep::UpdateFalling() } // If not drowning then falling. Note: peeps 'fall' after leaving a ride/enter the park. - TileElement* tile_element = map_get_first_element_at({ x, y }); + TileElement* tile_element = map_get_first_element_at(CoordsXY{ x, y }); TileElement* saved_map = nullptr; int32_t saved_height = 0; diff --git a/src/openrct2/rct1/S4Importer.cpp b/src/openrct2/rct1/S4Importer.cpp index 7c467b5b62..958f376cb8 100644 --- a/src/openrct2/rct1/S4Importer.cpp +++ b/src/openrct2/rct1/S4Importer.cpp @@ -2575,7 +2575,7 @@ namespace RCT1 { for (int32_t y = 0; y < RCT1_MAX_MAP_SIZE; y++) { - TileElement* tileElement = map_get_first_element_at(TileCoordsXY{ x, y }.ToCoordsXY()); + TileElement* tileElement = map_get_first_element_at(TileCoordsXY{ x, y }); if (tileElement == nullptr) continue; do diff --git a/src/openrct2/rct2/S6Importer.cpp b/src/openrct2/rct2/S6Importer.cpp index 5b5dab5620..9f224a8603 100644 --- a/src/openrct2/rct2/S6Importer.cpp +++ b/src/openrct2/rct2/S6Importer.cpp @@ -228,7 +228,7 @@ public: gDateMonthsElapsed = static_cast(_s6.elapsed_months); gDateMonthTicks = _s6.current_day; - gCurrentTicks = _s6.scenario_ticks; + gCurrentTicks = _s6.game_ticks_1; scenario_rand_seed(_s6.scenario_srand_0, _s6.scenario_srand_1); @@ -478,6 +478,7 @@ public: CheatsReset(); ClearRestrictedScenery(); } + void FixLandOwnership() const { if (String::Equals(_s6.scenario_filename, "Europe - European Cultural Festival.SC6")) @@ -1761,6 +1762,15 @@ template<> void S6Importer::ImportEntity(const RCT12SpriteBase& baseSrc dst->IsCrashedVehicle = src->flags & RCT12_SPRITE_FLAGS_IS_CRASHED_VEHICLE_SPRITE; } +static uint32_t AdjustScenarioToCurrentTicks(const rct_s6_data& s6, uint32_t tick) +{ + // Previously gScenarioTicks was used as a time point, now it's gCurrentTicks. + // gCurrentTicks and gScenarioTicks are now exported as the same, older saves that have a different + // scenario tick must account for the difference between the two. + uint32_t ticksElapsed = s6.scenario_ticks - tick; + return s6.game_ticks_1 - ticksElapsed; +} + template<> void S6Importer::ImportEntity(const RCT12SpriteBase& baseSrc) { auto dst = CreateEntityAt(baseSrc.sprite_index); @@ -1793,7 +1803,7 @@ template<> void S6Importer::ImportEntity(const RCT12SpriteBase& baseSrc) dst->TimeInQueue = src->time_in_queue; dst->CashInPocket = src->cash_in_pocket; dst->CashSpent = src->cash_spent; - dst->ParkEntryTime = src->park_entry_time; + dst->ParkEntryTime = AdjustScenarioToCurrentTicks(_s6, src->park_entry_time); dst->RejoinQueueTimeout = src->rejoin_queue_timeout; dst->PreviousRide = RCT12RideIdToOpenRCT2RideId(src->previous_ride); dst->PreviousRideTimeOut = src->previous_ride_time_out; @@ -1843,6 +1853,7 @@ template<> void S6Importer::ImportEntity(const RCT12SpriteBase& baseSrc) dst->AssignedStaffType = StaffType(src->staff_type); dst->MechanicTimeSinceCall = src->mechanic_time_since_call; + dst->HireDate = src->park_entry_time; dst->StaffOrders = src->staff_orders; dst->StaffMowingTimeout = src->staff_mowing_timeout; @@ -1967,7 +1978,7 @@ template<> void S6Importer::ImportEntity(const RCT12SpriteBase& baseSrc) auto src = static_cast(&baseSrc); ImportEntityCommonProperties(dst, src); dst->SubType = Litter::Type(src->type); - dst->creationTick = src->creationTick; + dst->creationTick = AdjustScenarioToCurrentTicks(_s6, src->creationTick); } void S6Importer::ImportEntity(const RCT12SpriteBase& src) diff --git a/src/openrct2/ride/Ride.cpp b/src/openrct2/ride/Ride.cpp index 412fb7af84..d2773269c0 100644 --- a/src/openrct2/ride/Ride.cpp +++ b/src/openrct2/ride/Ride.cpp @@ -2213,7 +2213,7 @@ static void ride_shop_connected(Ride* ride) return; TrackElement* trackElement = nullptr; - TileElement* tileElement = map_get_first_element_at(shopLoc.ToCoordsXY()); + TileElement* tileElement = map_get_first_element_at(shopLoc); do { if (tileElement == nullptr) @@ -2569,7 +2569,7 @@ void Ride::ChainQueues() const // This will fire for every entrance on this x, y and z, regardless whether that actually belongs to // the ride or not. - TileElement* tileElement = map_get_first_element_at(location.ToCoordsXY()); + TileElement* tileElement = map_get_first_element_at(location); if (tileElement != nullptr) { do @@ -2914,7 +2914,7 @@ static void ride_set_maze_entrance_exit_points(Ride* ride) { auto entranceExitMapPos = position->ToCoordsXYZ(); - TileElement* tileElement = map_get_first_element_at(position->ToCoordsXY()); + TileElement* tileElement = map_get_first_element_at(*position); do { if (tileElement == nullptr) @@ -5554,7 +5554,7 @@ void determine_ride_entrance_and_exit_locations() { for (int32_t y = 1; y < MAXIMUM_MAP_SIZE_TECHNICAL - 1; y++) { - TileElement* tileElement = map_get_first_element_at(TileCoordsXY{ x, y }.ToCoordsXY()); + TileElement* tileElement = map_get_first_element_at(TileCoordsXY{ x, y }); if (tileElement != nullptr) { diff --git a/src/openrct2/ride/RideConstruction.cpp b/src/openrct2/ride/RideConstruction.cpp index b48053cc75..18fafd2572 100644 --- a/src/openrct2/ride/RideConstruction.cpp +++ b/src/openrct2/ride/RideConstruction.cpp @@ -347,7 +347,7 @@ void ride_clear_blocked_tiles(Ride* ride) { for (int32_t x = 0; x < MAXIMUM_MAP_SIZE_TECHNICAL; x++) { - auto element = map_get_first_element_at(TileCoordsXY{ x, y }.ToCoordsXY()); + auto element = map_get_first_element_at(TileCoordsXY{ x, y }); if (element != nullptr) { do diff --git a/src/openrct2/ride/RideRatings.cpp b/src/openrct2/ride/RideRatings.cpp index 5517784300..f4805d10ad 100644 --- a/src/openrct2/ride/RideRatings.cpp +++ b/src/openrct2/ride/RideRatings.cpp @@ -1463,7 +1463,7 @@ static int32_t ride_ratings_get_scenery_score(Ride* ride) xx++) { // Count scenery items on this tile - TileElement* tileElement = map_get_first_element_at(TileCoordsXY{ xx, yy }.ToCoordsXY()); + TileElement* tileElement = map_get_first_element_at(TileCoordsXY{ xx, yy }); if (tileElement == nullptr) continue; do diff --git a/src/openrct2/ride/TrackDesign.cpp b/src/openrct2/ride/TrackDesign.cpp index 377dbac717..5e1684d3b2 100644 --- a/src/openrct2/ride/TrackDesign.cpp +++ b/src/openrct2/ride/TrackDesign.cpp @@ -359,7 +359,7 @@ rct_string_id TrackDesign::CreateTrackDesignMaze(const Ride& ride) { for (; x < MAXIMUM_MAP_SIZE_BIG; x += COORDS_XY_STEP) { - auto tileElement = map_get_first_element_at({ x, y }); + auto tileElement = map_get_first_element_at(CoordsXY{ x, y }); do { if (tileElement == nullptr) @@ -465,7 +465,7 @@ CoordsXYE TrackDesign::MazeGetFirstElement(const Ride& ride) { for (tile.x = 0; tile.x < MAXIMUM_MAP_SIZE_BIG; tile.x += COORDS_XY_STEP) { - tile.element = map_get_first_element_at({ tile.x, tile.y }); + tile.element = map_get_first_element_at(CoordsXY{ tile.x, tile.y }); do { if (tile.element == nullptr) diff --git a/src/openrct2/ride/TrackDesignSave.cpp b/src/openrct2/ride/TrackDesignSave.cpp index c6252a7500..90d5cbfb3c 100644 --- a/src/openrct2/ride/TrackDesignSave.cpp +++ b/src/openrct2/ride/TrackDesignSave.cpp @@ -624,7 +624,7 @@ static void track_design_save_select_nearby_scenery_for_tile(ride_id_t rideIndex { for (int32_t x = cx - TRACK_NEARBY_SCENERY_DISTANCE; x <= cx + TRACK_NEARBY_SCENERY_DISTANCE; x++) { - tileElement = map_get_first_element_at(TileCoordsXY{ x, y }.ToCoordsXY()); + tileElement = map_get_first_element_at(TileCoordsXY{ x, y }); if (tileElement == nullptr) continue; do diff --git a/src/openrct2/ride/Vehicle.cpp b/src/openrct2/ride/Vehicle.cpp index ce35781f99..44e8a8cfd7 100644 --- a/src/openrct2/ride/Vehicle.cpp +++ b/src/openrct2/ride/Vehicle.cpp @@ -1897,7 +1897,7 @@ void Vehicle::UpdateMeasurements() { // Set tile_element to first element. Since elements aren't always ordered by base height, // we must start at the first element and iterate through each tile element. - auto tileElement = map_get_first_element_at({ x, y }); + auto tileElement = map_get_first_element_at(CoordsXY{ x, y }); if (tileElement == nullptr) return; diff --git a/src/openrct2/ride/transport/Chairlift.cpp b/src/openrct2/ride/transport/Chairlift.cpp index db0b0a2950..101f424449 100644 --- a/src/openrct2/ride/transport/Chairlift.cpp +++ b/src/openrct2/ride/transport/Chairlift.cpp @@ -110,7 +110,7 @@ static void chairlift_paint_util_draw_supports(paint_session* session, int32_t s static const TrackElement* chairlift_paint_util_map_get_track_element_at_from_ride_fuzzy( int32_t x, int32_t y, int32_t z, const Ride* ride) { - const TileElement* tileElement = map_get_first_element_at({ x, y }); + const TileElement* tileElement = map_get_first_element_at(CoordsXY{ x, y }); if (tileElement == nullptr) { return nullptr; diff --git a/src/openrct2/world/Banner.cpp b/src/openrct2/world/Banner.cpp index 10d704a732..fa590e5a72 100644 --- a/src/openrct2/world/Banner.cpp +++ b/src/openrct2/world/Banner.cpp @@ -145,7 +145,7 @@ TileElement* banner_get_tile_element(BannerIndex bannerIndex) auto banner = GetBanner(bannerIndex); if (banner != nullptr) { - auto tileElement = map_get_first_element_at(banner->position.ToCoordsXY()); + auto tileElement = map_get_first_element_at(banner->position); if (tileElement != nullptr) { do @@ -166,7 +166,7 @@ WallElement* banner_get_scrolling_wall_tile_element(BannerIndex bannerIndex) if (banner == nullptr) return nullptr; - auto tileElement = map_get_first_element_at(banner->position.ToCoordsXY()); + auto tileElement = map_get_first_element_at(banner->position); if (tileElement == nullptr) return nullptr; diff --git a/src/openrct2/world/Footpath.cpp b/src/openrct2/world/Footpath.cpp index 0b0fd586cb..7d5424ce8f 100644 --- a/src/openrct2/world/Footpath.cpp +++ b/src/openrct2/world/Footpath.cpp @@ -1226,7 +1226,7 @@ void footpath_update_queue_chains() if (location.IsNull()) continue; - TileElement* tileElement = map_get_first_element_at(location.ToCoordsXY()); + TileElement* tileElement = map_get_first_element_at(location); if (tileElement != nullptr) { do @@ -2143,7 +2143,7 @@ static void footpath_remove_edges_towards(const CoordsXYRangedZ& footPathPos, in // entrances and exits, shops, paths). bool tile_element_wants_path_connection_towards(const TileCoordsXYZD& coords, const TileElement* const elementToBeRemoved) { - TileElement* tileElement = map_get_first_element_at(coords.ToCoordsXY()); + TileElement* tileElement = map_get_first_element_at(coords); if (tileElement == nullptr) return false; do diff --git a/src/openrct2/world/Map.cpp b/src/openrct2/world/Map.cpp index 46c4938d28..6a88ce3922 100644 --- a/src/openrct2/world/Map.cpp +++ b/src/openrct2/world/Map.cpp @@ -214,7 +214,7 @@ static void ReorganiseTileElements(size_t capacity) { for (int32_t x = 0; x < MAXIMUM_MAP_SIZE_TECHNICAL; x++) { - const auto* element = map_get_first_element_at(TileCoordsXY{ x, y }.ToCoordsXY()); + const auto* element = map_get_first_element_at(TileCoordsXY{ x, y }); if (element == nullptr) { newElements.push_back(GetDefaultSurfaceElement()); @@ -285,14 +285,14 @@ void tile_element_iterator_begin(tile_element_iterator* it) { it->x = 0; it->y = 0; - it->element = map_get_first_element_at({ 0, 0 }); + it->element = map_get_first_element_at(TileCoordsXY{ 0, 0 }); } int32_t tile_element_iterator_next(tile_element_iterator* it) { if (it->element == nullptr) { - it->element = map_get_first_element_at(TileCoordsXY{ it->x, it->y }.ToCoordsXY()); + it->element = map_get_first_element_at(TileCoordsXY{ it->x, it->y }); return 1; } @@ -305,7 +305,7 @@ int32_t tile_element_iterator_next(tile_element_iterator* it) if (it->x < (MAXIMUM_MAP_SIZE_TECHNICAL - 1)) { it->x++; - it->element = map_get_first_element_at(TileCoordsXY{ it->x, it->y }.ToCoordsXY()); + it->element = map_get_first_element_at(TileCoordsXY{ it->x, it->y }); return 1; } @@ -313,7 +313,7 @@ int32_t tile_element_iterator_next(tile_element_iterator* it) { it->x = 0; it->y++; - it->element = map_get_first_element_at(TileCoordsXY{ it->x, it->y }.ToCoordsXY()); + it->element = map_get_first_element_at(TileCoordsXY{ it->x, it->y }); return 1; } @@ -325,15 +325,26 @@ void tile_element_iterator_restart_for_tile(tile_element_iterator* it) it->element = nullptr; } -TileElement* map_get_first_element_at(const CoordsXY& elementPos) +static bool IsTileLocationValid(const TileCoordsXY& coords) { - if (!map_is_location_valid(elementPos)) + const bool is_x_valid = coords.x < MAXIMUM_MAP_SIZE_TECHNICAL && coords.x >= 0; + const bool is_y_valid = coords.y < MAXIMUM_MAP_SIZE_TECHNICAL && coords.y >= 0; + return is_x_valid && is_y_valid; +} + +TileElement* map_get_first_element_at(const TileCoordsXY& tilePos) +{ + if (!IsTileLocationValid(tilePos)) { log_verbose("Trying to access element outside of range"); return nullptr; } - auto tileElementPos = TileCoordsXY{ elementPos }; - return _tileIndex.GetFirstElementAt(tileElementPos); + return _tileIndex.GetFirstElementAt(tilePos); +} + +TileElement* map_get_first_element_at(const CoordsXY& elementPos) +{ + return map_get_first_element_at(TileCoordsXY{ elementPos }); } TileElement* map_get_nth_element_at(const CoordsXY& coords, int32_t n) @@ -680,7 +691,7 @@ int16_t tile_element_water_height(const CoordsXY& loc) */ bool map_coord_is_connected(const TileCoordsXYZ& loc, uint8_t faceDirection) { - TileElement* tileElement = map_get_first_element_at(loc.ToCoordsXY()); + TileElement* tileElement = map_get_first_element_at(loc); if (tileElement == nullptr) return false; diff --git a/src/openrct2/world/Map.h b/src/openrct2/world/Map.h index ab472b3567..ecc7679ade 100644 --- a/src/openrct2/world/Map.h +++ b/src/openrct2/world/Map.h @@ -192,7 +192,8 @@ void map_init(int32_t size); void map_count_remaining_land_rights(); void map_strip_ghost_flag_from_elements(); -TileElement* map_get_first_element_at(const CoordsXY& elementPos); +TileElement* map_get_first_element_at(const CoordsXY& tilePos); +TileElement* map_get_first_element_at(const TileCoordsXY& tilePos); TileElement* map_get_nth_element_at(const CoordsXY& coords, int32_t n); void map_set_tile_element(const TileCoordsXY& tilePos, TileElement* elements); int32_t map_height_from_slope(const CoordsXY& coords, int32_t slopeDirection, bool isSloped);