Merge remote-tracking branch 'upstream/develop' into new-save-format

This commit is contained in:
ζeh Matt 2021-09-23 22:28:17 +03:00
commit f689b4e4c8
No known key found for this signature in database
GPG Key ID: 18CE582C71A225B0
40 changed files with 131 additions and 105 deletions

View File

@ -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")

View File

@ -48,8 +48,8 @@
<TitleSequencesSha1>304d13a126c15bf2c86ff13b81a2f2cc1856ac8d</TitleSequencesSha1>
<ObjectsUrl>https://github.com/OpenRCT2/objects/releases/download/v1.2.1/objects.zip</ObjectsUrl>
<ObjectsSha1>540e004abc683b3fe22211f5234e3d78ab023c5f</ObjectsSha1>
<ReplaysUrl>https://github.com/OpenRCT2/replays/releases/download/v0.0.52/replays.zip</ReplaysUrl>
<ReplaysSha1>3A1A6B5B25ACA3B8AADC618A9D2BE44F8A23A7BB</ReplaysSha1>
<ReplaysUrl>https://github.com/OpenRCT2/replays/releases/download/v0.0.53/replays.zip</ReplaysUrl>
<ReplaysSha1>8DDA5F2CC0B101D477396A3B016FF5F3EDFD074F</ReplaysSha1>
</PropertyGroup>
<ItemGroup>

View File

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

View File

@ -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();
}

View File

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

View File

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

View File

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

View File

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

View File

@ -740,11 +740,11 @@ static void window_park_init_viewport(rct_window* w)
if (w->page != WINDOW_PARK_PAGE_ENTRANCE)
return;
std::optional<Focus2> focus = std::nullopt;
std::optional<Focus> 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())
{

View File

@ -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);

View File

@ -1589,7 +1589,7 @@ static void window_ride_init_viewport(rct_window* w)
int32_t viewSelectionIndex = w->ride.view - 1;
std::optional<Focus2> focus;
std::optional<Focus> 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 its best to just reset it.
w->focus = std::nullopt;
window_ride_init_viewport(w);
}

View File

@ -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);

View File

@ -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();

View File

@ -1339,7 +1339,7 @@ void window_staff_viewport_init(rct_window* w)
if (w->page != WINDOW_STAFF_OVERVIEW)
return;
std::optional<Focus2> focus;
std::optional<Focus> 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)
{

View File

@ -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);

View File

@ -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();

View File

@ -56,6 +56,7 @@ GameState::GameState()
void GameState::InitAll(int32_t mapSize)
{
gInMapInitCode = true;
gCurrentTicks = 0;
gCurrentTicks = 0;
map_init(mapSize);

View File

@ -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)

View File

@ -117,14 +117,14 @@ std::optional<ScreenCoordsXY> 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<decltype(arg)>;
if constexpr (std::is_same_v<T, Focus2::CoordinateFocus>)
if constexpr (std::is_same_v<T, Focus::CoordinateFocus>)
return arg;
else if constexpr (std::is_same_v<T, Focus2::EntityFocus>)
else if constexpr (std::is_same_v<T, Focus::EntityFocus>)
{
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<decltype(arg)>;
if constexpr (std::is_same_v<T, Focus2::CoordinateFocus>)
if constexpr (std::is_same_v<T, Focus::CoordinateFocus>)
return SPRITE_INDEX_NULL;
else if constexpr (std::is_same_v<T, Focus2::EntityFocus>)
else if constexpr (std::is_same_v<T, Focus::EntityFocus>)
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;
}

View File

@ -104,7 +104,7 @@ extern uint8_t gCurrentRotation;
void viewport_init_all();
std::optional<ScreenCoordsXY> 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);

View File

@ -195,7 +195,7 @@ struct rct_scroll
constexpr auto WINDOW_SCROLL_UNDEFINED = std::numeric_limits<uint16_t>::max();
struct Focus2
struct Focus
{
using CoordinateFocus = CoordsXYZ;
using EntityFocus = uint16_t;
@ -203,7 +203,7 @@ struct Focus2
uint8_t zoom = 0;
std::variant<CoordinateFocus, EntityFocus> data;
template<typename T> constexpr explicit Focus2(T newValue, uint8_t newZoom = 0)
template<typename T> 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);
}

View File

@ -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)

View File

@ -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> focus2;
std::optional<Focus> focus;
union
{
campaign_variables campaign;

View File

@ -310,12 +310,15 @@
<ClInclude Include="ride\coaster\JuniorRollerCoaster.h" />
<ClInclude Include="ride\coaster\meta\AirPoweredVerticalCoaster.h" />
<ClInclude Include="ride\coaster\meta\BobsleighCoaster.h" />
<ClInclude Include="ride\coaster\meta\ClassicMiniRollerCoaster.h" />
<ClInclude Include="ride\coaster\meta\CompactInvertedCoaster.h" />
<ClInclude Include="ride\coaster\meta\CorkscrewRollerCoaster.h" />
<ClInclude Include="ride\coaster\meta\FlyingRollerCoaster.h" />
<ClInclude Include="ride\coaster\meta\GigaCoaster.h" />
<ClInclude Include="ride\coaster\meta\HeartlineTwisterCoaster.h" />
<ClInclude Include="ride\coaster\meta\HybridCoaster.h" />
<ClInclude Include="ride\coaster\meta\Hypercoaster.h" />
<ClInclude Include="ride\coaster\meta\HyperTwister.h" />
<ClInclude Include="ride\coaster\meta\InvertedHairpinCoaster.h" />
<ClInclude Include="ride\coaster\meta\InvertedImpulseCoaster.h" />
<ClInclude Include="ride\coaster\meta\InvertedRollerCoaster.h" />
@ -332,6 +335,7 @@
<ClInclude Include="ride\coaster\meta\ReverserRollerCoaster.h" />
<ClInclude Include="ride\coaster\meta\SideFrictionRollerCoaster.h" />
<ClInclude Include="ride\coaster\meta\SingleRailRollerCoaster.h" />
<ClInclude Include="ride\coaster\meta\SpinningWildMouse.h" />
<ClInclude Include="ride\coaster\meta\SpiralRollerCoaster.h" />
<ClInclude Include="ride\coaster\meta\StandUpRollerCoaster.h" />
<ClInclude Include="ride\coaster\meta\SteelWildMouse.h" />
@ -356,6 +360,7 @@
<ClInclude Include="ride\gentle\meta\MiniGolf.h" />
<ClInclude Include="ride\gentle\meta\MiniHelicopters.h" />
<ClInclude Include="ride\gentle\meta\MonorailCycles.h" />
<ClInclude Include="ride\gentle\meta\MonsterTrucks.h" />
<ClInclude Include="ride\gentle\meta\ObservationTower.h" />
<ClInclude Include="ride\gentle\meta\SpaceRings.h" />
<ClInclude Include="ride\gentle\meta\SpiralSlide.h" />
@ -396,7 +401,9 @@
<ClInclude Include="ride\transport\meta\Monorail.h" />
<ClInclude Include="ride\transport\meta\SuspendedMonorail.h" />
<ClInclude Include="ride\Vehicle.h" />
<ClInclude Include="ride\VehicleColour.h" />
<ClInclude Include="ride\VehicleData.h" />
<ClInclude Include="ride\VehicleEntry.h" />
<ClInclude Include="ride\VehiclePaint.h" />
<ClInclude Include="ride\VehicleSubpositionData.h" />
<ClInclude Include="ride\water\meta\BoatHire.h" />

View File

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

View File

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

View File

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

View File

@ -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

View File

@ -228,7 +228,7 @@ public:
gDateMonthsElapsed = static_cast<int32_t>(_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<Vehicle>(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<Guest>(const RCT12SpriteBase& baseSrc)
{
auto dst = CreateEntityAt<Guest>(baseSrc.sprite_index);
@ -1793,7 +1803,7 @@ template<> void S6Importer::ImportEntity<Guest>(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<Staff>(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<Litter>(const RCT12SpriteBase& baseSrc)
auto src = static_cast<const RCT12SpriteLitter*>(&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)

View File

@ -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)
{

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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

View File

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

View File

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

View File

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

View File

@ -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

View File

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

View File

@ -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);